├── doc ├── UDP_IP_Stack.pdf ├── src │ ├── UDP_IP_Stack.pptx │ └── zero latency receive.jpg └── release_notes.txt ├── sw ├── test_results │ ├── UDPTest_console.txt │ ├── UDPTest_wireshark.pcap │ ├── UDPTestStream_wireshark.pcap │ └── UDPTestStream_console.txt ├── UDPTest.java ├── UDPTestStream.java └── UDPCxn.java ├── rtl └── vhdl │ ├── ipcores │ └── xilinx │ │ ├── README.txt │ │ ├── mac_layer_v2_1.xco │ │ └── mac_layer_v2_2.xco │ ├── axi.vhd │ ├── arp_types.vhd │ ├── ml605 │ ├── udp_constraints.ucf │ ├── IP_complete.vhd │ └── UDP_Complete.vhd │ ├── tx_arbitrator.vhd │ ├── ipv4_types.vhd │ ├── arp_SYNC.vhd │ ├── IPv4.vhd │ ├── UDP_Complete_nomac.vhd │ ├── arp_STORE_br.vhd │ ├── UDP_TX.vhd │ ├── arp_REQ.vhd │ ├── arp_TX.vhd │ ├── UDP_RX.vhd │ ├── arpv2.vhd │ └── arp_RX.vhd └── bench └── vhdl ├── UDP_TX_tb.vhd ├── UDP_RX_tb.vhd └── arp_STORE_tb.vhd /doc/UDP_IP_Stack.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/udp_ip_stack/HEAD/doc/UDP_IP_Stack.pdf -------------------------------------------------------------------------------- /doc/src/UDP_IP_Stack.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/udp_ip_stack/HEAD/doc/src/UDP_IP_Stack.pptx -------------------------------------------------------------------------------- /sw/test_results/UDPTest_console.txt: -------------------------------------------------------------------------------- 1 | Sending packet: 1=45~34=201~18=23~ on port 2000 2 | Got [@ABC] 3 | -------------------------------------------------------------------------------- /doc/src/zero latency receive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/udp_ip_stack/HEAD/doc/src/zero latency receive.jpg -------------------------------------------------------------------------------- /sw/test_results/UDPTest_wireshark.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/udp_ip_stack/HEAD/sw/test_results/UDPTest_wireshark.pcap -------------------------------------------------------------------------------- /sw/test_results/UDPTestStream_wireshark.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/udp_ip_stack/HEAD/sw/test_results/UDPTestStream_wireshark.pcap -------------------------------------------------------------------------------- /rtl/vhdl/ipcores/xilinx/README.txt: -------------------------------------------------------------------------------- 1 | The IP Core XCO files are xilinx core generator configuration files. 2 | They are provided as examples only and you may need to do some tweaking 3 | to the generated code to get it to work. 4 | 5 | mac_layer_v2_2.xco - is the current core I last tested with. 6 | 7 | mac_layer_v2_1.xco - is an earlier xilinx core that I originally developed with. 8 | The interface may have changed slightly, so you may need to make some small changes 9 | to the ml605/xv6mac_straight.vhd module to get it to work with this version. 10 | -------------------------------------------------------------------------------- /sw/UDPTest.java: -------------------------------------------------------------------------------- 1 | package com.pjf; 2 | 3 | import java.io.IOException; 4 | import java.net.SocketException; 5 | import java.net.UnknownHostException; 6 | 7 | public class UDPTest { 8 | private UDPCxn cxn; 9 | 10 | public UDPTest() throws SocketException, UnknownHostException { 11 | cxn = new UDPCxn("192.168.5.9"); 12 | } 13 | 14 | public void go() throws IOException { 15 | String fix1 = "1=45~34=201~18=23~"; 16 | cxn.fixSend(fix1, 2000, true); 17 | byte[] rep = cxn.rcv(); 18 | String reply = new String(rep); 19 | System.out.println("Got [" + reply + "]"); 20 | } 21 | 22 | 23 | public static void main(String[] args) { 24 | UDPTest ut; 25 | try { 26 | ut = new UDPTest(); 27 | ut.go(); 28 | } catch (Exception e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /rtl/vhdl/axi.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- Package File Template 3 | -- 4 | -- Purpose: This package defines data types for AXI transfers 5 | 6 | 7 | library IEEE; 8 | use IEEE.STD_LOGIC_1164.all; 9 | 10 | package axi is 11 | 12 | type axi_in_type is record 13 | data_in : STD_LOGIC_VECTOR (7 downto 0); 14 | data_in_valid : STD_LOGIC; -- indicates data_in valid on clock 15 | data_in_last : STD_LOGIC; -- indicates last data in frame 16 | end record; 17 | 18 | 19 | type axi_out_type is record 20 | data_out_valid : std_logic; -- indicates data out is valid 21 | data_out_last : std_logic; -- with data out valid indicates the last byte of a frame 22 | data_out : std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 23 | end record; 24 | 25 | end axi; 26 | -------------------------------------------------------------------------------- /sw/UDPTestStream.java: -------------------------------------------------------------------------------- 1 | package com.pjf; 2 | 3 | import java.io.IOException; 4 | import java.net.SocketException; 5 | import java.net.UnknownHostException; 6 | 7 | public class UDPTestStream { 8 | private UDPCxn cxn; 9 | private Listener listener; 10 | 11 | class Listener extends Thread { 12 | 13 | @Override 14 | public void run() { 15 | byte[] rep; 16 | while (true) { 17 | try { 18 | rep = cxn.rcv(); 19 | String reply = new String(rep); 20 | System.out.println("Got [" + reply + "]"); 21 | } catch (IOException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | } 26 | } 27 | 28 | public UDPTestStream() throws SocketException, UnknownHostException { 29 | cxn = new UDPCxn("192.168.5.9"); 30 | listener = new Listener(); 31 | listener.start(); 32 | } 33 | 34 | public void go() throws IOException, InterruptedException { 35 | String fix1 = "1=45~34="; 36 | String fix2 = "~18=23~"; 37 | for (int price=225; price>=150; price--) { 38 | StringBuffer fixmsg = new StringBuffer(fix1); 39 | fixmsg.append(Integer.toString(price)); 40 | fixmsg.append(fix2); 41 | System.out.println("Sending price tick " + price); 42 | cxn.fixSend(fixmsg.toString(), 2000, false); 43 | } 44 | Thread.sleep(2000); 45 | } 46 | 47 | 48 | public static void main(String[] args) { 49 | UDPTestStream ut; 50 | try { 51 | ut = new UDPTestStream(); 52 | ut.go(); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_types.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- Package File Template 3 | -- 4 | -- Purpose: This package defines supplemental types, subtypes, 5 | -- constants, and functions 6 | -- 7 | -- To use any of the example code shown below, uncomment the lines and modify as necessary 8 | -- 9 | -- Revision 0.02 - Added type definitions (store and network) for arpv2 10 | 11 | library IEEE; 12 | use IEEE.STD_LOGIC_1164.all; 13 | 14 | package arp_types is 15 | 16 | 17 | -- arp lookup types 18 | 19 | type arp_req_req_type is 20 | record 21 | lookup_req : std_logic; -- set high when wanting mac adr for the requested IP 22 | ip : std_logic_vector (31 downto 0); 23 | end record; 24 | 25 | type arp_req_rslt_type is 26 | record 27 | got_mac : std_logic; -- indicates that we got the mac 28 | mac : std_logic_vector (47 downto 0); 29 | got_err : std_logic; -- indicates that we got an error (prob a timeout) 30 | end record; 31 | 32 | type arp_entry_t is record 33 | ip : std_logic_vector (31 downto 0); 34 | mac : std_logic_vector (47 downto 0); 35 | end record; 36 | 37 | type arp_control_type is 38 | record 39 | clear_cache : std_logic; 40 | end record; 41 | 42 | -- arp store types 43 | 44 | type arp_store_rslt_t is (IDLE,BUSY,SEARCHING,FOUND,NOT_FOUND); 45 | 46 | type arp_store_rdrequest_t is 47 | record 48 | req : std_logic; -- request to lookup 49 | ip : std_logic_vector(31 downto 0); -- contains ip to lookup 50 | end record; 51 | 52 | type arp_store_wrrequest_t is 53 | record 54 | req : std_logic; -- request to store 55 | entry : arp_entry_t; -- ip,mac to store 56 | end record; 57 | 58 | type arp_store_result_t is 59 | record 60 | status : arp_store_rslt_t; -- status of the request 61 | entry : arp_entry_t; -- contains ip,mac if found 62 | end record; 63 | 64 | -- arp network types 65 | 66 | type arp_nwk_rslt_t is (IDLE,REQUESTING,RECEIVED,ERROR); 67 | 68 | type arp_nwk_request_t is 69 | record 70 | req : std_logic; -- request to resolve IP addr 71 | ip : std_logic_vector(31 downto 0); -- IP to request 72 | end record; 73 | 74 | type arp_nwk_result_t is 75 | record 76 | status : arp_nwk_rslt_t; -- status of request 77 | entry : arp_entry_t; -- the result 78 | end record; 79 | 80 | 81 | end arp_types; 82 | -------------------------------------------------------------------------------- /sw/UDPCxn.java: -------------------------------------------------------------------------------- 1 | package com.pjf; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | import java.net.SocketException; 8 | import java.net.UnknownHostException; 9 | 10 | 11 | public class UDPCxn { 12 | private DatagramSocket skt; 13 | private InetAddress dstIP; 14 | 15 | public UDPCxn(long dstIPadr) throws SocketException, UnknownHostException { 16 | skt = new DatagramSocket(); 17 | byte[] target = new byte[4]; 18 | target[0] = (byte) ((dstIPadr >> 24) & 0xff); 19 | target[1] = (byte) ((dstIPadr >> 16) & 0xff); 20 | target[2] = (byte) ((dstIPadr >> 8) & 0xff); 21 | target[3] = (byte) (dstIPadr & 0xff); 22 | dstIP = InetAddress.getByAddress(target); 23 | } 24 | 25 | public UDPCxn(String dstIPadr) throws SocketException, UnknownHostException { 26 | skt = new DatagramSocket(); 27 | String[] parts = dstIPadr.split("[.]"); 28 | if (parts.length != 4) { 29 | throw new UnknownHostException("ip addr must have 4 parts"); 30 | } 31 | byte[] target = new byte[4]; 32 | for (int i = 0; i<4; i++) { 33 | target[i] = (byte) Integer.parseInt(parts[i]); 34 | } 35 | dstIP = InetAddress.getByAddress(target); 36 | } 37 | 38 | public void send(byte[] data, int port) throws IOException { 39 | DatagramPacket pkt = new DatagramPacket(data, data.length, dstIP, port); 40 | System.out.println("Sending packet"); 41 | skt.send(pkt); 42 | } 43 | 44 | public void fixSend(String str, int port, boolean print) throws IOException { 45 | String s1 = str.replace('~','\001'); 46 | byte[] data = s1.getBytes(); 47 | DatagramPacket pkt = new DatagramPacket(data, data.length, dstIP, port); 48 | if (print) { 49 | System.out.println("Sending packet: " + str + " on port " + port); 50 | } 51 | skt.send(pkt); 52 | } 53 | 54 | 55 | public byte[] rcv() throws IOException { 56 | byte[] buf = new byte[1024]; 57 | DatagramPacket pkt = new DatagramPacket(buf, buf.length); 58 | // System.out.println("waiting to receive ..."); 59 | skt.receive(pkt); 60 | int len = pkt.getLength(); 61 | byte[] rd = pkt.getData(); 62 | byte[] data = new byte[len]; 63 | for (int i=0; i LOC = AC13 |IOSTANDARD = LVCMOS25; 42 | Net gmii_rxd<6> LOC = AC12 |IOSTANDARD = LVCMOS25; 43 | Net gmii_rxd<5> LOC = AD11 |IOSTANDARD = LVCMOS25; 44 | Net gmii_rxd<4> LOC = AM12 |IOSTANDARD = LVCMOS25; 45 | Net gmii_rxd<3> LOC = AN12 |IOSTANDARD = LVCMOS25; 46 | Net gmii_rxd<2> LOC = AE14 |IOSTANDARD = LVCMOS25; 47 | Net gmii_rxd<1> LOC = AF14 |IOSTANDARD = LVCMOS25; 48 | Net gmii_rxd<0> LOC = AN13 |IOSTANDARD = LVCMOS25; 49 | 50 | Net gmii_txd<7> LOC = AF11 |IOSTANDARD = LVCMOS25; 51 | Net gmii_txd<6> LOC = AE11 |IOSTANDARD = LVCMOS25; 52 | Net gmii_txd<5> LOC = AM10 |IOSTANDARD = LVCMOS25; 53 | Net gmii_txd<4> LOC = AL10 |IOSTANDARD = LVCMOS25; 54 | Net gmii_txd<3> LOC = AG11 |IOSTANDARD = LVCMOS25; 55 | Net gmii_txd<2> LOC = AG10 |IOSTANDARD = LVCMOS25; 56 | Net gmii_txd<1> LOC = AL11 |IOSTANDARD = LVCMOS25; 57 | Net gmii_txd<0> LOC = AM11 |IOSTANDARD = LVCMOS25; 58 | 59 | Net gmii_col LOC = AK13 |IOSTANDARD = LVCMOS25; 60 | Net gmii_crs LOC = AL13 |IOSTANDARD = LVCMOS25; 61 | Net mii_tx_clk LOC = AD12 |IOSTANDARD = LVCMOS25; 62 | 63 | Net gmii_tx_en LOC = AJ10 |IOSTANDARD = LVCMOS25; 64 | Net gmii_tx_er LOC = AH10 |IOSTANDARD = LVCMOS25; 65 | Net gmii_tx_clk LOC = AH12 |IOSTANDARD = LVCMOS25; 66 | 67 | Net gmii_rx_dv LOC = AM13 |IOSTANDARD = LVCMOS25; 68 | Net gmii_rx_er LOC = AG12 |IOSTANDARD = LVCMOS25; 69 | # P20 - GCLK7 70 | Net gmii_rx_clk LOC = AP11 |IOSTANDARD = LVCMOS25; 71 | 72 | 73 | 74 | NET "clk_in_p" TNM_NET = "clk_in_p"; 75 | TIMESPEC "TS_emac1_clk_in_p" = PERIOD "clk_in_p" 5.000 ns HIGH 50% INPUT_JITTER 50.0ps; 76 | 77 | 78 | # Ethernet GTX_CLK high quality 125 MHz reference clock 79 | NET "*mac_block/gtx_clk_bufg" TNM_NET = "ref_gtx_clk"; 80 | TIMEGRP "emac1_clk_ref_gtx" = "ref_gtx_clk"; 81 | TIMESPEC TS_emac1_clk_ref_gtx = PERIOD "N/A" 8 ns HIGH 50%; 82 | 83 | 84 | -------------------------------------------------------------------------------- /rtl/vhdl/ipcores/xilinx/mac_layer_v2_2.xco: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # Xilinx Core Generator version 13.4 4 | # Date: Sat Apr 21 12:31:20 2012 5 | # 6 | ############################################################## 7 | # 8 | # This file contains the customisation parameters for a 9 | # Xilinx CORE Generator IP GUI. It is strongly recommended 10 | # that you do not manually alter this file as it may cause 11 | # unexpected and unsupported behavior. 12 | # 13 | ############################################################## 14 | # 15 | # Generated from component: xilinx.com:ip:v6_emac:2.2 16 | # 17 | ############################################################## 18 | # 19 | # BEGIN Project Options 20 | SET addpads = false 21 | SET asysymbol = true 22 | SET busformat = BusFormatAngleBracketNotRipped 23 | SET createndf = false 24 | SET designentry = VHDL 25 | SET device = xc6vlx240t 26 | SET devicefamily = virtex6 27 | SET flowvendor = Other 28 | SET formalverification = false 29 | SET foundationsym = false 30 | SET implementationfiletype = Ngc 31 | SET package = ff1156 32 | SET removerpms = false 33 | SET simulationfiles = Structural 34 | SET speedgrade = -1 35 | SET verilogsim = false 36 | SET vhdlsim = true 37 | # END Project Options 38 | # BEGIN Select 39 | SELECT Virtex-6_Embedded_Tri-Mode_Ethernet_MAC_Wrapper family Xilinx,_Inc. 2.2 40 | # END Select 41 | # BEGIN Parameters 42 | CSET address_filter=false 43 | CSET address_filter_enable=false 44 | CSET axi_ipif=true 45 | CSET client_side_data_width=8_bit 46 | CSET clock_enable=true 47 | CSET component_name=mac_layer_v2_2 48 | CSET management_interface=false 49 | CSET mdio=false 50 | CSET number_of_address_table_entries=0 51 | CSET phy_an_enable=false 52 | CSET phy_ignore_adzero=false 53 | CSET phy_isolate=false 54 | CSET phy_link_timer_value=13D 55 | CSET phy_loopback_in_gtp=false 56 | CSET phy_loopback_msb=false 57 | CSET phy_powerdown=false 58 | CSET phy_reset=false 59 | CSET phy_unidirection_enable=false 60 | CSET physical_interface=GMII 61 | CSET rx_ctrl_lencheck_disable=false 62 | CSET rx_disable_length=false 63 | CSET rx_enable=true 64 | CSET rx_flow_control_enable=false 65 | CSET rx_half_duplex_enable=false 66 | CSET rx_in_band_fcs_enable=false 67 | CSET rx_jumbo_frame_enable=false 68 | CSET rx_reset=false 69 | CSET rx_vlan_enable=false 70 | CSET serial_mode_switch_enable=false 71 | CSET sgmii_mode=No_clock 72 | CSET speed=1000_Mbps 73 | CSET statistics_counters=false 74 | CSET statistics_reset=true 75 | CSET statistics_width=32bit 76 | CSET tx_enable=true 77 | CSET tx_flow_control_enable=false 78 | CSET tx_half_duplex_enable=false 79 | CSET tx_ifg_adjust_enable=false 80 | CSET tx_in_band_fcs_enable=false 81 | CSET tx_jumbo_frame_enable=false 82 | CSET tx_reset=false 83 | CSET tx_vlan_enable=false 84 | CSET unicast_pause_mac_address_1=AA 85 | CSET unicast_pause_mac_address_2=BB 86 | CSET unicast_pause_mac_address_3=CC 87 | CSET unicast_pause_mac_address_4=DD 88 | CSET unicast_pause_mac_address_5=EE 89 | CSET unicast_pause_mac_address_6=FF 90 | # END Parameters 91 | # BEGIN Extra information 92 | MISC pkg_timestamp=2012-01-07T15:29:19Z 93 | # END Extra information 94 | GENERATE 95 | # CRC: 107b69dd 96 | -------------------------------------------------------------------------------- /sw/test_results/UDPTestStream_console.txt: -------------------------------------------------------------------------------- 1 | Sending price tick 225 2 | Sending price tick 224 3 | Sending price tick 223 4 | Sending price tick 222 5 | Sending price tick 221 6 | Sending price tick 220 7 | Sending price tick 219 8 | Sending price tick 218 9 | Sending price tick 217 10 | Sending price tick 216 11 | Sending price tick 215 12 | Sending price tick 214 13 | Sending price tick 213 14 | Sending price tick 212 15 | Sending price tick 211 16 | Sending price tick 210 17 | Sending price tick 209 18 | Sending price tick 208 19 | Sending price tick 207 20 | Sending price tick 206 21 | Sending price tick 205 22 | Sending price tick 204 23 | Sending price tick 203 24 | Sending price tick 202 25 | Got [@ABC] 26 | Got [@ABC] 27 | Got [@ABC] 28 | Got [@ABC] 29 | Got [@ABC] 30 | Got [@ABC] 31 | Got [@ABC] 32 | Got [@ABC] 33 | Got [@ABC] 34 | Got [@ABC] 35 | Got [@ABC] 36 | Got [@ABC] 37 | Got [@ABC] 38 | Got [@ABC] 39 | Got [@ABC] 40 | Got [@ABC] 41 | Got [@ABC] 42 | Got [@ABC] 43 | Got [@ABC] 44 | Got [@ABC] 45 | Got [@ABC] 46 | Got [@ABC] 47 | Got [@ABC] 48 | Got [@ABC] 49 | Sending price tick 201 50 | Sending price tick 200 51 | Sending price tick 199 52 | Got [@ABC] 53 | Sending price tick 198 54 | Sending price tick 197 55 | Got [@ABC] 56 | Got [@ABC] 57 | Got [@ABC] 58 | Got [@ABC] 59 | Sending price tick 196 60 | Sending price tick 195 61 | Got [@ABC] 62 | Sending price tick 194 63 | Sending price tick 193 64 | Got [@ABC] 65 | Sending price tick 192 66 | Sending price tick 191 67 | Got [@ABC] 68 | Sending price tick 190 69 | Got [@ABC] 70 | Got [@ABC] 71 | Got [@ABC] 72 | Got [@ABC] 73 | Sending price tick 189 74 | Sending price tick 188 75 | Sending price tick 187 76 | Got [@ABC] 77 | Got [@ABC] 78 | Sending price tick 186 79 | Got [@ABC] 80 | Sending price tick 185 81 | Sending price tick 184 82 | Got [@ABC] 83 | Sending price tick 183 84 | Got [@ABC] 85 | Got [@ABC] 86 | Got [@ABC] 87 | Sending price tick 182 88 | Sending price tick 181 89 | Got [@ABC] 90 | Sending price tick 180 91 | Got [@ABC] 92 | Sending price tick 179 93 | Got [@ABC] 94 | Sending price tick 178 95 | Sending price tick 177 96 | Got [@ABC] 97 | Sending price tick 176 98 | Got [@ABC] 99 | Sending price tick 175 100 | Got [@ABC] 101 | Got [@ABC] 102 | Sending price tick 174 103 | Sending price tick 173 104 | Got [@ABC] 105 | Sending price tick 172 106 | Got [@ABC] 107 | Got [@ABC] 108 | Got [@ABC] 109 | Sending price tick 171 110 | Sending price tick 170 111 | Got [@ABC] 112 | Sending price tick 169 113 | Sending price tick 168 114 | Got [@ABC] 115 | Sending price tick 167 116 | Sending price tick 166 117 | Got [@ABC] 118 | Sending price tick 165 119 | Got [@ABC] 120 | Got [@ABC] 121 | Got [@ABC] 122 | Got [@ABC] 123 | Sending price tick 164 124 | Got [@ABC] 125 | Sending price tick 163 126 | Sending price tick 162 127 | Got [@ABC] 128 | Sending price tick 161 129 | Got [@ABC] 130 | Sending price tick 160 131 | Got [@ABC] 132 | Sending price tick 159 133 | Sending price tick 158 134 | Got [@ABC] 135 | Sending price tick 157 136 | Sending price tick 156 137 | Got [@ABC] 138 | Sending price tick 155 139 | Got [@ABC] 140 | Sending price tick 154 141 | Got [@ABC] 142 | Sending price tick 153 143 | Got [@ABC] 144 | Sending price tick 152 145 | Got [@ABC] 146 | Got [@ABC] 147 | Got [@ABC] 148 | Got [@ABC] 149 | Sending price tick 151 150 | Sending price tick 150 151 | Got [@ABC] 152 | Got [@ABC] 153 | -------------------------------------------------------------------------------- /rtl/vhdl/tx_arbitrator.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 08:03:30 06/04/2011 6 | -- Design Name: 7 | -- Module Name: tx_arbitrator - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: arbitrate between two sources that want to transmit onto a bus 12 | -- handles arbitration and multiplexing 13 | -- 14 | -- Dependencies: 15 | -- 16 | -- Revision: 17 | -- Revision 0.01 - File Created 18 | -- Revision 0.02 - Made sticky on port M1 to optimise access on this port and allow immediate grant 19 | -- Revision 0.03 - Added first 20 | -- Additional Comments: 21 | -- 22 | ---------------------------------------------------------------------------------- 23 | library IEEE; 24 | use IEEE.STD_LOGIC_1164.ALL; 25 | 26 | 27 | entity tx_arbitrator is 28 | port ( 29 | clk : in std_logic; 30 | reset : in std_logic; 31 | 32 | req_1 : in std_logic; 33 | grant_1 : out std_logic; 34 | data_1 : in std_logic_vector(7 downto 0); -- data byte to tx 35 | valid_1 : in std_logic; -- tdata is valid 36 | first_1 : in std_logic; -- indicates first byte of frame 37 | last_1 : in std_logic; -- indicates last byte of frame 38 | 39 | req_2 : in std_logic; 40 | grant_2 : out std_logic; 41 | data_2 : in std_logic_vector(7 downto 0); -- data byte to tx 42 | valid_2 : in std_logic; -- tdata is valid 43 | first_2 : in std_logic; -- indicates first byte of frame 44 | last_2 : in std_logic; -- indicates last byte of frame 45 | 46 | data : out std_logic_vector(7 downto 0); -- data byte to tx 47 | valid : out std_logic; -- tdata is valid 48 | first : out std_logic; -- indicates first byte of frame 49 | last : out std_logic -- indicates last byte of frame 50 | ); 51 | end tx_arbitrator; 52 | 53 | architecture Behavioral of tx_arbitrator is 54 | 55 | type grant_type is (M1,M2); 56 | 57 | signal grant : grant_type; 58 | 59 | begin 60 | combinatorial : process ( 61 | grant, 62 | data_1, valid_1, first_1, last_1, 63 | data_2, valid_2, first_2, last_2 64 | ) 65 | begin 66 | -- grant outputs 67 | case grant is 68 | when M1 => 69 | grant_1 <= '1'; 70 | grant_2 <= '0'; 71 | when M2 => 72 | grant_1 <= '0'; 73 | grant_2 <= '1'; 74 | end case; 75 | 76 | -- multiplexer 77 | if grant = M1 then 78 | data <= data_1; 79 | valid <= valid_1; 80 | first <= first_1; 81 | last <= last_1; 82 | else 83 | data <= data_2; 84 | valid <= valid_2; 85 | first <= first_2; 86 | last <= last_2; 87 | end if; 88 | end process; 89 | 90 | sequential : process (clk, reset, req_1, req_2, grant) 91 | begin 92 | if rising_edge(clk) then 93 | if reset = '1' then 94 | grant <= M1; 95 | else 96 | case grant is 97 | when M1 => 98 | if req_1 = '1' then 99 | grant <= M1; 100 | elsif req_2 = '1' then 101 | grant <= M2; 102 | end if; 103 | when M2 => 104 | if req_2 = '1' then 105 | grant <= M2; 106 | else 107 | grant <= M1; 108 | end if; 109 | end case; 110 | end if; 111 | end if; 112 | end process; 113 | 114 | 115 | end Behavioral; 116 | 117 | -------------------------------------------------------------------------------- /doc/release_notes.txt: -------------------------------------------------------------------------------- 1 | V2.1 - Updates contributed by Tim Brooks. 2 | 3 | - To resolve the mac address of an IP address off the local network, I believe the "Who-has" has to be sent to the IP address of the default gateway (or router). For that to happen ARP has to know the address of the default gateway and the net mask. 4 | In the tar ball I've attached, I modified ARP_req.vhd to provide this functionality. I may be useful to you or someone else who downloads the core... also updated the tb to check this. 5 | - Bugs fixed by Tim Brooks: 6 | -- In IPV4_TX, I've removed signal "mac_data_out_ready_reg". It was causing tx_count to be wrong by 1 at the end of a transfer where mac_data_out_ready when low during the transfer. IP_tx_tb didn't catch it. I use Xilinx Isim and it seems that "wait for clk_period" causes signals to change, in effect, just before the clock. I replaced with wait until clk = '1' thorough that test-bench, which assure that the signal changes as if it where clocked. You may want to check this with your simulator and, if you have similar results, you may want to change "wait for clk_period" to "wait until clk = '1'" throughout your test-benches... 7 | -- In ARP_req.vhd, the statements on lines 192&193 would cause the cache to be updated and "got_mac" signal to go high on the next clock, even if the received IP address resolved was not what was asked for. 8 | -- This was also masked by the fact that the test-bench checks "to early" for the "Got_mac" signal staying low (or going high for that matter). For T7.2, I've moved the Assert statements to the same clock period as the data_in_last signal going low. probably should be done for other tests as well 9 | -- ARP_rx, in my system, from the soft Ethernet core, data_in_last usually occurs when rx_count = 41. this means that rx_state never goes to process_arp. I've modified this so that it is processed on rx_count = 41 and outside of the "else" statement of data_in_last = 1 catch. 10 | -- arp_tx. Replies should not be broadcast. I replaced the hard coded FFs in the destination mac field with target.mac, having it set to all 1s as default. 11 | -- There are 2 places that were causing timing problems for my spartan 6 setup. read_result in ARP_store_br. I just added a pipeline stage and that problem went away. 12 | in ipv4_rx, putting the decision as to whether the packet is for and should be processed in case rx_count = 0013 was a problem. I've spread that decision over 0010 to 0013 as it was before the broadcast address test was added. setting or clearing Set_is_broadcast is still in rx_count= 0013. 13 | --------------------------------------------------------------------- 14 | 15 | 16 | V1.3 - Added ARP timeout and ability to reset the ARP IP/MAC cache 17 | Migration notes: v1.2 to v1.3 - UDP_complete_nomac and IP_Complete_nomac have generics 18 | to specify clock rate and ARP timeout, and an additional control input. 19 | The generics can be left at their default values, the control input should have clear_cache set to '0'. 20 | --------------------------------------------------------------------- 21 | 22 | 23 | V1.2 - Added handling for receipt of IP pkts with broadcast address ff.ff.ff.ff. Added is_broadcast flag 24 | to IP RX hdr. 25 | - Added ability to transmit IP pkts to broadcast address. 26 | Migration Notes: V1.1 to V1.2 - IP_RX_HDR has an additional output signal to indicate the IP pkt 27 | was received on the broadcast address. 28 | --------------------------------------------------------------------- 29 | 30 | V1.1 - Added mac_tx_tfirst output to assist coupling to MAC layers that require a start of frame indication. 31 | Migration Notes: V1.0 to V1.1 32 | - The entity declaration for UDP_Complete_nomac and IP_Complete_nomac have changed. 33 | - if you dont need to use the new mac_tx_tfirst output, leave it open. 34 | --------------------------------------------------------------------- 35 | 36 | V1.0 - initial release 37 | -------------------------------------------------------------------------------- /rtl/vhdl/ipv4_types.vhd: -------------------------------------------------------------------------------- 1 | -- 2 | -- 3 | -- Purpose: This package defines types for use in IPv4 4 | 5 | 6 | library IEEE; 7 | use IEEE.STD_LOGIC_1164.all; 8 | use work.axi.all; 9 | use work.arp_types.all; 10 | 11 | package ipv4_types is 12 | 13 | constant IP_BC_ADDR : std_logic_vector (31 downto 0) := x"ffffffff"; 14 | constant MAC_BC_ADDR : std_logic_vector (47 downto 0) := x"ffffffffffff"; 15 | 16 | -------------- 17 | -- IPv4 TX -- 18 | -------------- 19 | 20 | -- coding for result in tx 21 | constant IPTX_RESULT_NONE : std_logic_vector (1 downto 0) := "00"; 22 | constant IPTX_RESULT_SENDING : std_logic_vector (1 downto 0) := "01"; 23 | constant IPTX_RESULT_ERR : std_logic_vector (1 downto 0) := "10"; 24 | constant IPTX_RESULT_SENT : std_logic_vector (1 downto 0) := "11"; 25 | 26 | type ipv4_tx_header_type is record 27 | protocol : std_logic_vector (7 downto 0); 28 | data_length : STD_LOGIC_VECTOR (15 downto 0); -- user data size, bytes 29 | dst_ip_addr : STD_LOGIC_VECTOR (31 downto 0); 30 | end record; 31 | 32 | type ipv4_tx_type is record 33 | hdr : ipv4_tx_header_type; -- header to tx 34 | data : axi_out_type; -- tx axi bus 35 | end record; 36 | 37 | 38 | -------------- 39 | -- IPv4 RX -- 40 | -------------- 41 | 42 | -- coding for last_error_code in rx hdr 43 | constant RX_EC_NONE : std_logic_vector (3 downto 0) := x"0"; 44 | constant RX_EC_ET_ETH : std_logic_vector (3 downto 0) := x"1"; -- early termination in ETH hdr phase 45 | constant RX_EC_ET_IP : std_logic_vector (3 downto 0) := x"2"; -- early termination in IP hdr phase 46 | constant RX_EC_ET_USER : std_logic_vector (3 downto 0) := x"3"; -- early termination in USER DATA phase 47 | 48 | type ipv4_rx_header_type is record 49 | is_valid : std_logic; 50 | protocol : std_logic_vector (7 downto 0); 51 | data_length : STD_LOGIC_VECTOR (15 downto 0); -- user data size, bytes 52 | src_ip_addr : STD_LOGIC_VECTOR (31 downto 0); 53 | num_frame_errors : std_logic_vector (7 downto 0); 54 | last_error_code : std_logic_vector (3 downto 0); -- see RX_EC_xxx constants 55 | is_broadcast : std_logic; -- set if the msg received is a broadcast 56 | end record; 57 | 58 | type ipv4_rx_type is record 59 | hdr : ipv4_rx_header_type; -- header received 60 | data : axi_in_type; -- rx axi bus 61 | end record; 62 | 63 | type ip_control_type is record 64 | arp_controls : arp_control_type; 65 | end record; 66 | 67 | ------------ 68 | -- UDP TX -- 69 | ------------ 70 | 71 | -- coding for result in tx 72 | constant UDPTX_RESULT_NONE : std_logic_vector (1 downto 0) := "00"; 73 | constant UDPTX_RESULT_SENDING : std_logic_vector (1 downto 0) := "01"; 74 | constant UDPTX_RESULT_ERR : std_logic_vector (1 downto 0) := "10"; 75 | constant UDPTX_RESULT_SENT : std_logic_vector (1 downto 0) := "11"; 76 | 77 | type udp_tx_header_type is record 78 | dst_ip_addr : STD_LOGIC_VECTOR (31 downto 0); 79 | dst_port : STD_LOGIC_VECTOR (15 downto 0); 80 | src_port : STD_LOGIC_VECTOR (15 downto 0); 81 | data_length : STD_LOGIC_VECTOR (15 downto 0); -- user data size, bytes 82 | checksum : STD_LOGIC_VECTOR (15 downto 0); 83 | end record; 84 | 85 | 86 | type udp_tx_type is record 87 | hdr : udp_tx_header_type; -- header received 88 | data : axi_out_type; -- tx axi bus 89 | end record; 90 | 91 | 92 | ------------ 93 | -- UDP RX -- 94 | ------------ 95 | 96 | type udp_rx_header_type is record 97 | is_valid : std_logic; 98 | src_ip_addr : STD_LOGIC_VECTOR (31 downto 0); 99 | src_port : STD_LOGIC_VECTOR (15 downto 0); 100 | dst_port : STD_LOGIC_VECTOR (15 downto 0); 101 | data_length : STD_LOGIC_VECTOR (15 downto 0); -- user data size, bytes 102 | end record; 103 | 104 | 105 | type udp_rx_type is record 106 | hdr : udp_rx_header_type; -- header received 107 | data : axi_in_type; -- rx axi bus 108 | end record; 109 | 110 | type udp_addr_type is record 111 | ip_addr : STD_LOGIC_VECTOR (31 downto 0); 112 | port_num : STD_LOGIC_VECTOR (15 downto 0); 113 | end record; 114 | 115 | type udp_control_type is record 116 | ip_controls : ip_control_type; 117 | end record; 118 | 119 | 120 | end ipv4_types; 121 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_SYNC.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 14:09:01 02/20/2012 6 | -- Design Name: 7 | -- Module Name: arp_SYNC - Behavioral - synchronises between rx and tx clock domains 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Additional Comments: 18 | -- 19 | ---------------------------------------------------------------------------------- 20 | library IEEE; 21 | use IEEE.STD_LOGIC_1164.all; 22 | use IEEE.NUMERIC_STD.all; 23 | use work.arp_types.all; 24 | 25 | entity arp_SYNC is 26 | port ( 27 | -- REQ to TX 28 | arp_nwk_req : in arp_nwk_request_t; -- request for a translation from IP to MAC 29 | send_who_has : out std_logic; 30 | ip_entry : out std_logic_vector (31 downto 0); 31 | -- RX to TX 32 | recv_who_has : in std_logic; -- this is for us, we will respond 33 | arp_entry_for_who_has : in arp_entry_t; 34 | send_I_have : out std_logic; 35 | arp_entry : out arp_entry_t; 36 | -- RX to REQ 37 | I_have_received : in std_logic; 38 | nwk_result_status : out arp_nwk_rslt_t; 39 | -- System Signals 40 | rx_clk : in std_logic; 41 | tx_clk : in std_logic; 42 | reset : in std_logic 43 | ); 44 | end arp_SYNC; 45 | 46 | architecture Behavioral of arp_SYNC is 47 | 48 | type sync_state_t is (IDLE, HOLD1, HOLD2); 49 | 50 | -- state registers 51 | signal ip_entry_state : sync_state_t; 52 | signal arp_entry_state : sync_state_t; 53 | signal ip_entry_reg : std_logic_vector (31 downto 0); 54 | signal arp_entry_reg : arp_entry_t; 55 | 56 | -- synchronisation registers 57 | signal send_who_has_r1 : std_logic; 58 | signal send_who_has_r2 : std_logic; 59 | signal send_I_have_r1 : std_logic; 60 | signal send_I_have_r2 : std_logic; 61 | 62 | begin 63 | 64 | combinatorial : process ( 65 | -- input signals 66 | arp_nwk_req, recv_who_has, arp_entry_for_who_has, I_have_received, reset, 67 | -- state 68 | ip_entry_state, ip_entry_reg, arp_entry_state, arp_entry_reg, 69 | -- synchronisation registers 70 | send_who_has_r1, send_who_has_r2, 71 | send_I_have_r1, send_I_have_r2 72 | ) 73 | begin 74 | -- set output followers 75 | send_who_has <= send_who_has_r2; 76 | ip_entry <= ip_entry_reg; 77 | send_I_have <= send_I_have_r2; 78 | arp_entry <= arp_entry_reg; 79 | 80 | -- combinaltorial outputs 81 | if I_have_received = '1' then 82 | nwk_result_status <= RECEIVED; 83 | else 84 | nwk_result_status <= IDLE; 85 | end if; 86 | end process; 87 | 88 | -- process for stablisising RX clock domain data registers 89 | -- essentially holds data registers ip_entry and arp_entry static for 2 rx clk cycles 90 | -- during transfer to TX clk domain 91 | rx_sequential : process (tx_clk) 92 | begin 93 | if rising_edge(tx_clk) then 94 | if reset = '1' then 95 | -- reset state variables 96 | ip_entry_reg <= (others => '0'); 97 | arp_entry_reg.ip <= (others => '0'); 98 | arp_entry_reg.mac <= (others => '0'); 99 | else 100 | -- normal (non reset) processing 101 | case ip_entry_state is 102 | when IDLE => 103 | if arp_nwk_req.req = '1' then 104 | ip_entry_reg <= arp_nwk_req.ip; 105 | ip_entry_state <= HOLD1; 106 | else 107 | ip_entry_reg <= ip_entry_reg; 108 | ip_entry_state <= IDLE; 109 | end if; 110 | when HOLD1 => 111 | ip_entry_reg <= ip_entry_reg; 112 | ip_entry_state <= HOLD2; 113 | when HOLD2 => 114 | ip_entry_reg <= ip_entry_reg; 115 | ip_entry_state <= IDLE; 116 | end case; 117 | 118 | case arp_entry_state is 119 | when IDLE => 120 | if recv_who_has = '1' then 121 | arp_entry_reg <= arp_entry_for_who_has; 122 | arp_entry_state <= HOLD1; 123 | else 124 | arp_entry_reg <= arp_entry_reg; 125 | arp_entry_state <= IDLE; 126 | end if; 127 | when HOLD1 => 128 | arp_entry_reg <= arp_entry_reg; 129 | arp_entry_state <= HOLD2; 130 | when HOLD2 => 131 | arp_entry_reg <= arp_entry_reg; 132 | arp_entry_state <= IDLE; 133 | end case; 134 | end if; 135 | end if; 136 | end process; 137 | 138 | -- process for syncing to the TX clock domain 139 | -- clocks control signals through 2 layers of tx clocking 140 | tx_sequential : process (tx_clk) 141 | begin 142 | if rising_edge(tx_clk) then 143 | if reset = '1' then 144 | -- reset state variables 145 | send_who_has_r1 <= '0'; 146 | send_who_has_r2 <= '0'; 147 | send_I_have_r1 <= '0'; 148 | send_I_have_r2 <= '0'; 149 | else 150 | -- normal (non reset) processing 151 | 152 | send_who_has_r1 <= arp_nwk_req.req; 153 | send_who_has_r2 <= send_who_has_r1; 154 | 155 | send_I_have_r1 <= recv_who_has; 156 | send_I_have_r2 <= send_I_have_r1; 157 | end if; 158 | end if; 159 | end process; 160 | 161 | 162 | end Behavioral; 163 | 164 | -------------------------------------------------------------------------------- /rtl/vhdl/IPv4.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 16:20:42 06/01/2011 6 | -- Design Name: 7 | -- Module Name: IPv4 - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle simple IP RX and TX 13 | -- doesnt handle seg & reass 14 | -- dest MAC addr resolution through ARP layer 15 | -- Handle IPv4 protocol 16 | -- Respond to ARP requests and replies 17 | -- Ignore pkts that are not IP 18 | -- Ignore pkts that are not addressed to us-- 19 | -- Dependencies: 20 | -- 21 | -- Revision: 22 | -- Revision 0.01 - File Created 23 | -- Revision 0.02 - separated RX and TX clocks 24 | -- Revision 0.03 - Added mac_data_out_first 25 | -- Additional Comments: 26 | -- 27 | ---------------------------------------------------------------------------------- 28 | LIBRARY ieee; 29 | USE ieee.std_logic_1164.ALL; 30 | use IEEE.NUMERIC_STD.ALL; 31 | use work.axi.all; 32 | use work.ipv4_types.all; 33 | use work.arp_types.all; 34 | 35 | entity IPv4 is 36 | Port ( 37 | -- IP Layer signals 38 | ip_tx_start : in std_logic; 39 | ip_tx : in ipv4_tx_type; -- IP tx cxns 40 | ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission) 41 | ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data 42 | ip_rx_start : out std_logic; -- indicates receipt of ip frame. 43 | ip_rx : out ipv4_rx_type; 44 | -- system control signals 45 | rx_clk : in STD_LOGIC; 46 | tx_clk : in STD_LOGIC; 47 | reset : in STD_LOGIC; 48 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 49 | our_mac_address : in std_logic_vector (47 downto 0); 50 | -- system status signals 51 | rx_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 52 | -- ARP lookup signals 53 | arp_req_req : out arp_req_req_type; 54 | arp_req_rslt : in arp_req_rslt_type; 55 | -- MAC layer RX signals 56 | mac_data_in : in STD_LOGIC_VECTOR (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 57 | mac_data_in_valid : in STD_LOGIC; -- indicates data_in valid on clock 58 | mac_data_in_last : in STD_LOGIC; -- indicates last data in frame 59 | -- MAC layer TX signals 60 | mac_tx_req : out std_logic; -- indicates that ip wants access to channel (stays up for as long as tx) 61 | mac_tx_granted : in std_logic; -- indicates that access to channel has been granted 62 | mac_data_out_ready : in std_logic; -- indicates system ready to consume data 63 | mac_data_out_valid : out std_logic; -- indicates data out is valid 64 | mac_data_out_first : out std_logic; -- with data out valid indicates the first byte of a frame 65 | mac_data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame 66 | mac_data_out : out std_logic_vector (7 downto 0) -- ethernet frame (from dst mac addr through to last byte of frame) 67 | ); 68 | end IPv4; 69 | 70 | architecture structural of IPv4 is 71 | 72 | COMPONENT IPv4_TX 73 | PORT( 74 | -- IP Layer signals 75 | ip_tx_start : in std_logic; 76 | ip_tx : in ipv4_tx_type; -- IP tx cxns 77 | ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission) 78 | ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data 79 | 80 | -- system signals 81 | clk : in STD_LOGIC; -- same clock used to clock mac data and ip data 82 | reset : in STD_LOGIC; 83 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 84 | our_mac_address : in std_logic_vector (47 downto 0); 85 | -- ARP lookup signals 86 | arp_req_req : out arp_req_req_type; 87 | arp_req_rslt : in arp_req_rslt_type; 88 | -- MAC layer TX signals 89 | mac_tx_req : out std_logic; -- indicates that ip wants access to channel (stays up for as long as tx) 90 | mac_tx_granted : in std_logic; -- indicates that access to channel has been granted 91 | mac_data_out_ready : in std_logic; -- indicates system ready to consume data 92 | mac_data_out_valid : out std_logic; -- indicates data out is valid 93 | mac_data_out_first : out std_logic; -- with data out valid indicates the first byte of a frame 94 | mac_data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame 95 | mac_data_out : out std_logic_vector (7 downto 0) -- ethernet frame (from dst mac addr through to last byte of frame) 96 | ); 97 | END COMPONENT; 98 | 99 | COMPONENT IPv4_RX 100 | PORT( 101 | -- IP Layer signals 102 | ip_rx : out ipv4_rx_type; 103 | ip_rx_start : out std_logic; -- indicates receipt of ip frame. 104 | -- system signals 105 | clk : in STD_LOGIC; 106 | reset : in STD_LOGIC; 107 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 108 | rx_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 109 | -- MAC layer RX signals 110 | mac_data_in : in STD_LOGIC_VECTOR (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 111 | mac_data_in_valid : in STD_LOGIC; -- indicates data_in valid on clock 112 | mac_data_in_last : in STD_LOGIC -- indicates last data in frame 113 | ); 114 | END COMPONENT; 115 | 116 | begin 117 | 118 | TX : IPv4_TX PORT MAP ( 119 | ip_tx_start => ip_tx_start, 120 | ip_tx => ip_tx, 121 | ip_tx_result => ip_tx_result, 122 | ip_tx_data_out_ready=> ip_tx_data_out_ready, 123 | clk => tx_clk, 124 | reset => reset, 125 | our_ip_address => our_ip_address, 126 | our_mac_address => our_mac_address, 127 | arp_req_req => arp_req_req, 128 | arp_req_rslt => arp_req_rslt, 129 | mac_tx_req => mac_tx_req, 130 | mac_tx_granted => mac_tx_granted, 131 | mac_data_out_ready => mac_data_out_ready, 132 | mac_data_out_valid => mac_data_out_valid, 133 | mac_data_out_first => mac_data_out_first, 134 | mac_data_out_last => mac_data_out_last, 135 | mac_data_out => mac_data_out 136 | ); 137 | 138 | RX : IPv4_RX PORT MAP ( 139 | ip_rx => ip_rx, 140 | ip_rx_start => ip_rx_start, 141 | clk => rx_clk, 142 | reset => reset, 143 | our_ip_address => our_ip_address, 144 | rx_pkt_count => rx_pkt_count, 145 | mac_data_in => mac_data_in, 146 | mac_data_in_valid => mac_data_in_valid, 147 | mac_data_in_last => mac_data_in_last 148 | ); 149 | 150 | 151 | end structural; 152 | 153 | -------------------------------------------------------------------------------- /bench/vhdl/UDP_TX_tb.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 18:43:49 06/10/2011 6 | -- Design Name: 7 | -- Module Name: C:/Users/pjf/Documents/projects/fpga/xilinx/Network/ip1/UDP_TX_tb.vhd 8 | -- Project Name: ip1 9 | -- Target Device: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- VHDL Test Bench Created by ISE for module: UDP_TX 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created 19 | -- Additional Comments: 20 | -- 21 | -- Notes: 22 | -- This testbench has been automatically generated using types std_logic and 23 | -- std_logic_vector for the ports of the unit under test. Xilinx recommends 24 | -- that these types always be used for the top-level I/O of a design in order 25 | -- to guarantee that the testbench will bind correctly to the post-implementation 26 | -- simulation model. 27 | -------------------------------------------------------------------------------- 28 | library IEEE; 29 | use IEEE.STD_LOGIC_1164.ALL; 30 | use IEEE.NUMERIC_STD.ALL; 31 | use work.axi.all; 32 | use work.ipv4_types.all; 33 | 34 | ENTITY UDP_TX_tb IS 35 | END UDP_TX_tb; 36 | 37 | ARCHITECTURE behavior OF UDP_TX_tb IS 38 | 39 | -- Component Declaration for the Unit Under Test (UUT) 40 | 41 | COMPONENT UDP_TX 42 | PORT( 43 | -- UDP Layer signals 44 | udp_tx_start : in std_logic; -- indicates req to tx UDP 45 | udp_txi : in udp_tx_type; -- UDP tx cxns 46 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 47 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 48 | -- system signals 49 | clk : in STD_LOGIC; -- same clock used to clock mac data and ip data 50 | reset : in STD_LOGIC; 51 | -- IP layer TX signals 52 | ip_tx_start : out std_logic; 53 | ip_tx : out ipv4_tx_type; -- IP tx cxns 54 | ip_tx_result : in std_logic_vector (1 downto 0); -- tx status (changes during transmission) 55 | ip_tx_data_out_ready : in std_logic -- indicates IP TX is ready to take data 56 | ); 57 | END COMPONENT; 58 | 59 | 60 | --Inputs 61 | signal udp_tx_start : std_logic := '0'; 62 | signal clk : std_logic := '0'; 63 | signal reset : std_logic := '0'; 64 | signal udp_txi : udp_tx_type; 65 | signal ip_tx_result : std_logic_vector (1 downto 0); -- tx status (changes during transmission) 66 | signal ip_tx_data_out_ready : std_logic; -- indicates IP TX is ready to take data 67 | 68 | --Outputs 69 | signal ip_tx_start : std_logic := '0'; 70 | signal ip_tx : ipv4_tx_type; 71 | signal udp_tx_result : std_logic_vector (1 downto 0); 72 | signal udp_tx_data_out_ready : std_logic; 73 | 74 | -- Clock period definitions 75 | constant clk_period : time := 8 ns; 76 | 77 | BEGIN 78 | 79 | -- Instantiate the Unit Under Test (UUT) 80 | uut: UDP_TX PORT MAP ( 81 | udp_tx_start => udp_tx_start, 82 | udp_txi => udp_txi, 83 | udp_tx_result => udp_tx_result, 84 | udp_tx_data_out_ready => udp_tx_data_out_ready, 85 | clk => clk, 86 | reset => reset, 87 | ip_tx_start => ip_tx_start, 88 | ip_tx => ip_tx, 89 | ip_tx_result => ip_tx_result, 90 | ip_tx_data_out_ready => ip_tx_data_out_ready 91 | ); 92 | 93 | 94 | -- Clock process definitions 95 | clk_process :process 96 | begin 97 | clk <= '0'; 98 | wait for clk_period/2; 99 | clk <= '1'; 100 | wait for clk_period/2; 101 | end process; 102 | 103 | 104 | -- Stimulus process 105 | stim_proc: process 106 | begin 107 | -- hold reset state for 100 ns. 108 | wait for 100 ns; 109 | 110 | udp_tx_start <= '0'; 111 | 112 | udp_txi.hdr.dst_ip_addr <= (others => '0'); 113 | udp_txi.hdr.dst_port <= (others => '0'); 114 | udp_txi.hdr.src_port <= (others => '0'); 115 | udp_txi.hdr.data_length <= (others => '0'); 116 | udp_txi.hdr.checksum <= (others => '0'); 117 | udp_txi.data.data_out_last <= '0'; 118 | 119 | reset <= '1'; 120 | wait for clk_period*10; 121 | reset <= '0'; 122 | wait for clk_period*5; 123 | 124 | -- check reset conditions 125 | 126 | assert ip_tx_start = '0' report "ip_tx_start not initialised correctly on reset"; 127 | assert ip_tx.data.data_out_valid = '0' report "ip_tx.data.data_out_valid not initialised correctly on reset"; 128 | assert ip_tx.data.data_out_last = '0' report "ip_tx.data.data_out_last not initialised correctly on reset"; 129 | assert udp_tx_result = UDPTX_RESULT_NONE report "udp_tx_result not initialised correctly on reset"; 130 | 131 | -- insert stimulus here 132 | 133 | wait for clk_period*5; 134 | 135 | ------------ 136 | -- TEST 1 -- basic functional tx test 137 | ------------ 138 | 139 | report "T1: basic functional tx test - send 56, 57, 58 to port 8532"; 140 | 141 | udp_txi.hdr.dst_ip_addr <= x"c0123478"; 142 | udp_txi.hdr.dst_port <= x"1467"; 143 | udp_txi.hdr.src_port <= x"8532"; 144 | udp_txi.hdr.data_length <= x"0003"; 145 | 146 | udp_tx_start <= '1'; 147 | ip_tx_data_out_ready <= '1'; -- IP layer can accept data 148 | wait for clk_period; 149 | udp_tx_start <= '0'; wait for clk_period; 150 | ip_tx_result <= IPTX_RESULT_NONE; 151 | 152 | assert udp_tx_result = UDPTX_RESULT_SENDING report "T1: result should be UDPTX_RESULT_SENDING"; 153 | 154 | wait until udp_tx_data_out_ready = '1'; 155 | 156 | -- start to tx IP data 157 | udp_txi.data.data_out_valid <= '1'; 158 | udp_txi.data.data_out <= x"56"; wait for clk_period; 159 | udp_txi.data.data_out <= x"57"; wait for clk_period; 160 | 161 | udp_txi.data.data_out <= x"58"; 162 | udp_txi.data.data_out_last <= '1'; 163 | wait for clk_period; 164 | 165 | assert ip_tx.data.data_out_last = '1' report "T1: ip_tx.datda_out_last not set on last byte"; 166 | 167 | udp_txi.data.data_out_valid <= '0'; 168 | udp_txi.data.data_out_last <= '0'; 169 | wait for clk_period*2; 170 | ip_tx_result <= IPTX_RESULT_SENT; 171 | 172 | assert udp_tx_result = UDPTX_RESULT_SENT report "T1: result should be UDPTX_RESULT_SENT"; 173 | wait for clk_period*2; 174 | 175 | ------------ 176 | -- TEST 2 -- 2nd pkt 177 | ------------ 178 | 179 | report "T2: send a second pkt - 56,57,58,59 to port 8532"; 180 | 181 | udp_txi.hdr.dst_ip_addr <= x"c0123475"; 182 | udp_txi.hdr.dst_port <= x"1467"; 183 | udp_txi.hdr.src_port <= x"8532"; 184 | udp_txi.hdr.data_length <= x"0005"; 185 | 186 | udp_tx_start <= '1'; 187 | ip_tx_data_out_ready <= '1'; -- IP layer can accept data 188 | wait for clk_period; 189 | udp_tx_start <= '0'; wait for clk_period; 190 | 191 | assert udp_tx_result = UDPTX_RESULT_SENDING report "T1: result should be UDPTX_RESULT_SENDING"; 192 | 193 | wait until udp_tx_data_out_ready = '1'; 194 | 195 | -- start to tx IP data 196 | udp_txi.data.data_out_valid <= '1'; 197 | udp_txi.data.data_out <= x"56"; wait for clk_period; 198 | udp_txi.data.data_out <= x"57"; wait for clk_period; 199 | udp_txi.data.data_out <= x"58"; wait for clk_period; 200 | udp_txi.data.data_out <= x"59"; wait for clk_period; 201 | 202 | udp_txi.data.data_out <= x"5a"; 203 | udp_txi.data.data_out_last <= '1'; 204 | wait for clk_period; 205 | assert ip_tx.data.data_out_last = '1' report "T1: ip_tx.datda_out_last not set on last byte"; 206 | 207 | udp_txi.data.data_out_valid <= '0'; 208 | udp_txi.data.data_out_last <= '0'; 209 | wait for clk_period*2; 210 | 211 | assert udp_tx_result = UDPTX_RESULT_SENT report "T1: result should be UDPTX_RESULT_SENT"; 212 | wait for clk_period*2; 213 | 214 | report "--- end of tests ---"; 215 | 216 | wait; 217 | end process; 218 | 219 | END; 220 | -------------------------------------------------------------------------------- /rtl/vhdl/UDP_Complete_nomac.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 09:38:49 06/13/2011 6 | -- Design Name: 7 | -- Module Name: UDP_Complete_nomac - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Revision 0.02 - separated RX and TX clocks 18 | -- Revision 0.03 - Added mac_tx_tfirst 19 | -- Additional Comments: 20 | -- 21 | ---------------------------------------------------------------------------------- 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.ALL; 24 | use IEEE.NUMERIC_STD.ALL; 25 | use work.axi.all; 26 | use work.ipv4_types.all; 27 | use work.arp_types.all; 28 | 29 | entity UDP_Complete_nomac is 30 | generic ( 31 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 32 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 33 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 34 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 35 | ); 36 | Port ( 37 | -- UDP TX signals 38 | udp_tx_start : in std_logic; -- indicates req to tx UDP 39 | udp_txi : in udp_tx_type; -- UDP tx cxns 40 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 41 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 42 | -- UDP RX signals 43 | udp_rx_start : out std_logic; -- indicates receipt of udp header 44 | udp_rxo : out udp_rx_type; 45 | -- IP RX signals 46 | ip_rx_hdr : out ipv4_rx_header_type; 47 | -- system signals 48 | rx_clk : in STD_LOGIC; 49 | tx_clk : in STD_LOGIC; 50 | reset : in STD_LOGIC; 51 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 52 | our_mac_address : in std_logic_vector (47 downto 0); 53 | control : in udp_control_type; 54 | -- status signals 55 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 56 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 57 | -- MAC Transmitter 58 | mac_tx_tdata : out std_logic_vector(7 downto 0); -- data byte to tx 59 | mac_tx_tvalid : out std_logic; -- tdata is valid 60 | mac_tx_tready : in std_logic; -- mac is ready to accept data 61 | mac_tx_tfirst : out std_logic; -- indicates first byte of frame 62 | mac_tx_tlast : out std_logic; -- indicates last byte of frame 63 | -- MAC Receiver 64 | mac_rx_tdata : in std_logic_vector(7 downto 0); -- data byte received 65 | mac_rx_tvalid : in std_logic; -- indicates tdata is valid 66 | mac_rx_tready : out std_logic; -- tells mac that we are ready to take data 67 | mac_rx_tlast : in std_logic -- indicates last byte of the trame 68 | ); 69 | end UDP_Complete_nomac; 70 | 71 | 72 | 73 | 74 | 75 | architecture structural of UDP_Complete_nomac is 76 | 77 | ------------------------------------------------------------------------------ 78 | -- Component Declaration for UDP TX 79 | ------------------------------------------------------------------------------ 80 | 81 | COMPONENT UDP_TX 82 | PORT( 83 | -- UDP Layer signals 84 | udp_tx_start : in std_logic; -- indicates req to tx UDP 85 | udp_txi : in udp_tx_type; -- UDP tx cxns 86 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 87 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 88 | -- system signals 89 | clk : in STD_LOGIC; -- same clock used to clock mac data and ip data 90 | reset : in STD_LOGIC; 91 | -- IP layer TX signals 92 | ip_tx_start : out std_logic; 93 | ip_tx : out ipv4_tx_type; -- IP tx cxns 94 | ip_tx_result : in std_logic_vector (1 downto 0); -- tx status (changes during transmission) 95 | ip_tx_data_out_ready : in std_logic -- indicates IP TX is ready to take data 96 | ); 97 | END COMPONENT; 98 | 99 | ------------------------------------------------------------------------------ 100 | -- Component Declaration for UDP RX 101 | ------------------------------------------------------------------------------ 102 | 103 | COMPONENT UDP_RX 104 | PORT( 105 | -- UDP Layer signals 106 | udp_rx_start : out std_logic; -- indicates receipt of udp header 107 | udp_rxo : out udp_rx_type; 108 | -- system signals 109 | clk : in STD_LOGIC; 110 | reset : in STD_LOGIC; 111 | -- IP layer RX signals 112 | ip_rx_start : in std_logic; -- indicates receipt of ip header 113 | ip_rx : in ipv4_rx_type 114 | ); 115 | END COMPONENT; 116 | 117 | ------------------------------------------------------------------------------ 118 | -- Component Declaration for the IP layer 119 | ------------------------------------------------------------------------------ 120 | 121 | component IP_complete_nomac 122 | generic ( 123 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 124 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 125 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 126 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 127 | ); 128 | Port ( 129 | -- IP Layer signals 130 | ip_tx_start : in std_logic; 131 | ip_tx : in ipv4_tx_type; -- IP tx cxns 132 | ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission) 133 | ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data 134 | ip_rx_start : out std_logic; -- indicates receipt of ip frame. 135 | ip_rx : out ipv4_rx_type; 136 | -- system signals 137 | rx_clk : in STD_LOGIC; 138 | tx_clk : in STD_LOGIC; 139 | reset : in STD_LOGIC; 140 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 141 | our_mac_address : in std_logic_vector (47 downto 0); 142 | control : in ip_control_type; 143 | -- status signals 144 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 145 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 146 | -- MAC Transmitter 147 | mac_tx_tdata : out std_logic_vector(7 downto 0); -- data byte to tx 148 | mac_tx_tvalid : out std_logic; -- tdata is valid 149 | mac_tx_tready : in std_logic; -- mac is ready to accept data 150 | mac_tx_tfirst : out std_logic; -- indicates first byte of frame 151 | mac_tx_tlast : out std_logic; -- indicates last byte of frame 152 | -- MAC Receiver 153 | mac_rx_tdata : in std_logic_vector(7 downto 0); -- data byte received 154 | mac_rx_tvalid : in std_logic; -- indicates tdata is valid 155 | mac_rx_tready : out std_logic; -- tells mac that we are ready to take data 156 | mac_rx_tlast : in std_logic -- indicates last byte of the trame 157 | ); 158 | end component; 159 | 160 | -- IP TX connectivity 161 | signal ip_tx_int : ipv4_tx_type; 162 | signal ip_tx_start_int : std_logic; 163 | signal ip_tx_result_int : std_logic_vector (1 downto 0); 164 | signal ip_tx_data_out_ready_int : std_logic; 165 | 166 | -- IP RX connectivity 167 | signal ip_rx_int : ipv4_rx_type; 168 | signal ip_rx_start_int : std_logic := '0'; 169 | 170 | 171 | begin 172 | 173 | -- output followers 174 | ip_rx_hdr <= ip_rx_int.hdr; 175 | 176 | -- Instantiate the UDP TX block 177 | udp_tx_block: UDP_TX 178 | PORT MAP ( 179 | -- UDP Layer signals 180 | udp_tx_start => udp_tx_start, 181 | udp_txi => udp_txi, 182 | udp_tx_result => udp_tx_result, 183 | udp_tx_data_out_ready=> udp_tx_data_out_ready, 184 | -- system signals 185 | clk => tx_clk, 186 | reset => reset, 187 | -- IP layer TX signals 188 | ip_tx_start => ip_tx_start_int, 189 | ip_tx => ip_tx_int, 190 | ip_tx_result => ip_tx_result_int, 191 | ip_tx_data_out_ready => ip_tx_data_out_ready_int 192 | ); 193 | 194 | -- Instantiate the UDP RX block 195 | udp_rx_block: UDP_RX PORT MAP ( 196 | -- UDP Layer signals 197 | udp_rxo => udp_rxo, 198 | udp_rx_start => udp_rx_start, 199 | -- system signals 200 | clk => rx_clk, 201 | reset => reset, 202 | -- IP layer RX signals 203 | ip_rx_start => ip_rx_start_int, 204 | ip_rx => ip_rx_int 205 | ); 206 | 207 | ------------------------------------------------------------------------------ 208 | -- Instantiate the IP layer 209 | ------------------------------------------------------------------------------ 210 | IP_block : IP_complete_nomac 211 | generic map ( 212 | CLOCK_FREQ => CLOCK_FREQ, 213 | ARP_TIMEOUT => ARP_TIMEOUT, 214 | ARP_MAX_PKT_TMO => ARP_MAX_PKT_TMO, 215 | MAX_ARP_ENTRIES => MAX_ARP_ENTRIES 216 | ) 217 | PORT MAP ( 218 | -- IP interface 219 | ip_tx_start => ip_tx_start_int, 220 | ip_tx => ip_tx_int, 221 | ip_tx_result => ip_tx_result_int, 222 | ip_tx_data_out_ready => ip_tx_data_out_ready_int, 223 | ip_rx_start => ip_rx_start_int, 224 | ip_rx => ip_rx_int, 225 | -- System interface 226 | rx_clk => rx_clk, 227 | tx_clk => tx_clk, 228 | reset => reset, 229 | our_ip_address => our_ip_address, 230 | our_mac_address => our_mac_address, 231 | control => control.ip_controls, 232 | -- status signals 233 | arp_pkt_count => arp_pkt_count, 234 | ip_pkt_count => ip_pkt_count, 235 | -- MAC Transmitter 236 | mac_tx_tdata => mac_tx_tdata, 237 | mac_tx_tvalid => mac_tx_tvalid, 238 | mac_tx_tready => mac_tx_tready, 239 | mac_tx_tfirst => mac_tx_tfirst, 240 | mac_tx_tlast => mac_tx_tlast, 241 | -- MAC Receiver 242 | mac_rx_tdata => mac_rx_tdata, 243 | mac_rx_tvalid => mac_rx_tvalid, 244 | mac_rx_tready => mac_rx_tready, 245 | mac_rx_tlast => mac_rx_tlast 246 | ); 247 | 248 | 249 | end structural; 250 | 251 | 252 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_STORE_br.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 12:00:04 05/31/2011 6 | -- Design Name: 7 | -- Module Name: arp_STORE_br - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- ARP storage table using block ram with lookup based on IP address 13 | -- implements upto 255 entries with sequential search 14 | -- uses round robin overwrite when full (LRU would be better, but ...) 15 | -- 16 | -- store may take a number of cycles and the request is latched 17 | -- lookup may take a number of cycles. Assumes that request signals remain valid during lookup 18 | -- 19 | -- Dependencies: 20 | -- 21 | -- Revision: 22 | -- Revision 0.01 - File Created 23 | -- Additional Comments: 24 | -- 25 | ---------------------------------------------------------------------------------- 26 | library IEEE; 27 | use IEEE.STD_LOGIC_1164.all; 28 | use IEEE.NUMERIC_STD.all; 29 | use ieee.std_logic_unsigned.all; 30 | use work.arp_types.all; 31 | 32 | entity arp_STORE_br is 33 | generic ( 34 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the store 35 | ); 36 | port ( 37 | -- read signals 38 | read_req : in arp_store_rdrequest_t; -- requesting a lookup or store 39 | read_result : out arp_store_result_t; -- the result 40 | -- write signals 41 | write_req : in arp_store_wrrequest_t; -- requesting a lookup or store 42 | -- control and status signals 43 | clear_store : in std_logic; -- erase all entries 44 | entry_count : out unsigned(7 downto 0); -- how many entries currently in store 45 | -- system signals 46 | clk : in std_logic; 47 | reset : in std_logic 48 | ); 49 | end arp_STORE_br; 50 | 51 | architecture Behavioral of arp_STORE_br is 52 | 53 | type st_state_t is (IDLE, PAUSE, SEARCH, FOUND, NOT_FOUND); 54 | 55 | type ip_ram_t is array (0 to MAX_ARP_ENTRIES-1) of std_logic_vector(31 downto 0); 56 | type mac_ram_t is array (0 to MAX_ARP_ENTRIES-1) of std_logic_vector(47 downto 0); 57 | subtype addr_t is integer range 0 to MAX_ARP_ENTRIES; 58 | 59 | type count_mode_t is (RST, INCR, HOLD); 60 | 61 | type mode_t is (MREAD, MWRITE); 62 | 63 | -- state variables 64 | signal ip_ram : ip_ram_t; -- will be implemented as block ram 65 | signal mac_ram : mac_ram_t; -- will be implemented as block ram 66 | signal st_state : st_state_t; 67 | signal next_write_addr : addr_t; -- where to make the next write 68 | signal num_entries : addr_t; -- number of entries in the store 69 | signal next_read_addr : addr_t; -- next addr to read from 70 | signal entry_found : arp_entry_t; -- entry found in search 71 | signal mode : mode_t; -- are we writing or reading? 72 | signal req_entry : arp_entry_t; -- entry latched from req 73 | 74 | -- busses 75 | signal next_st_state : st_state_t; 76 | signal arp_entry_val : arp_entry_t; 77 | signal mode_val : mode_t; 78 | signal write_addr : addr_t; -- actual write address to use 79 | signal read_result_int : arp_store_result_t; 80 | 81 | -- control signals 82 | signal set_st_state : std_logic; 83 | signal set_next_write_addr : count_mode_t; 84 | signal set_num_entries : count_mode_t; 85 | signal set_next_read_addr : count_mode_t; 86 | signal write_ram : std_logic; 87 | signal set_entry_found : std_logic; 88 | signal set_mode : std_logic; 89 | 90 | function read_status(status : arp_store_rslt_t; signal mode : mode_t) return arp_store_rslt_t is 91 | variable ret : arp_store_rslt_t; 92 | begin 93 | case status is 94 | when IDLE => 95 | ret := status; 96 | when others => 97 | if mode = MWRITE then 98 | ret := BUSY; 99 | else 100 | ret := status; 101 | end if; 102 | end case; 103 | return ret; 104 | end read_status; 105 | 106 | begin 107 | combinatorial : process ( 108 | -- input signals 109 | read_req, write_req, clear_store, reset, 110 | -- state variables 111 | ip_ram, mac_ram, st_state, next_write_addr, num_entries, 112 | next_read_addr, entry_found, mode, req_entry, 113 | -- busses 114 | next_st_state, arp_entry_val, mode_val, write_addr, read_result_int, 115 | -- control signals 116 | set_st_state, set_next_write_addr, set_num_entries, set_next_read_addr, set_entry_found, 117 | write_ram, set_mode 118 | ) 119 | begin 120 | -- set output followers 121 | read_result_int.status <= IDLE; 122 | read_result_int.entry <= entry_found; 123 | entry_count <= to_unsigned(num_entries, 8); 124 | 125 | -- set bus defaults 126 | next_st_state <= IDLE; 127 | mode_val <= MREAD; 128 | write_addr <= next_write_addr; 129 | 130 | -- set signal defaults 131 | set_st_state <= '0'; 132 | set_next_write_addr <= HOLD; 133 | set_num_entries <= HOLD; 134 | set_next_read_addr <= HOLD; 135 | write_ram <= '0'; 136 | set_entry_found <= '0'; 137 | set_mode <= '0'; 138 | 139 | -- STORE FSM 140 | case st_state is 141 | when IDLE => 142 | if write_req.req = '1' then 143 | -- need to search to see if this IP already there 144 | set_next_read_addr <= RST; -- start lookup from beginning 145 | mode_val <= MWRITE; 146 | set_mode <= '1'; 147 | next_st_state <= PAUSE; 148 | set_st_state <= '1'; 149 | elsif read_req.req = '1' then 150 | set_next_read_addr <= RST; -- start lookup from beginning 151 | mode_val <= MREAD; 152 | set_mode <= '1'; 153 | next_st_state <= PAUSE; 154 | set_st_state <= '1'; 155 | end if; 156 | 157 | when PAUSE => 158 | -- wait until read addr is latched and we get first data out of the ram 159 | read_result_int.status <= read_status(BUSY, mode); 160 | set_next_read_addr <= INCR; 161 | next_st_state <= SEARCH; 162 | set_st_state <= '1'; 163 | 164 | when SEARCH => 165 | read_result_int.status <= read_status(SEARCHING, mode); 166 | -- check if have a match at this entry 167 | if req_entry.ip = arp_entry_val.ip and next_read_addr <= num_entries then 168 | -- found it 169 | set_entry_found <= '1'; 170 | next_st_state <= FOUND; 171 | set_st_state <= '1'; 172 | elsif next_read_addr > num_entries or next_read_addr >= MAX_ARP_ENTRIES then 173 | -- reached end of entry table 174 | read_result_int.status <= read_status(NOT_FOUND, mode); 175 | next_st_state <= NOT_FOUND; 176 | set_st_state <= '1'; 177 | else 178 | -- no match at this entry , go to next 179 | set_next_read_addr <= INCR; 180 | end if; 181 | 182 | when FOUND => 183 | read_result_int.status <= read_status(FOUND, mode); 184 | if mode = MWRITE then 185 | write_addr <= next_read_addr - 1; 186 | write_ram <= '1'; 187 | next_st_state <= IDLE; 188 | set_st_state <= '1'; 189 | elsif read_req.req = '0' then -- wait in this state until request de-asserted 190 | next_st_state <= IDLE; 191 | set_st_state <= '1'; 192 | end if; 193 | 194 | when NOT_FOUND => 195 | read_result_int.status <= read_status(NOT_FOUND, mode); 196 | if mode = MWRITE then 197 | -- need to write into the next free slot 198 | write_addr <= next_write_addr; 199 | write_ram <= '1'; 200 | set_next_write_addr <= INCR; 201 | if num_entries < MAX_ARP_ENTRIES then 202 | -- if not full, count another entry (if full, it just wraps) 203 | set_num_entries <= INCR; 204 | end if; 205 | next_st_state <= IDLE; 206 | set_st_state <= '1'; 207 | elsif read_req.req = '0' then -- wait in this state until request de-asserted 208 | next_st_state <= IDLE; 209 | set_st_state <= '1'; 210 | end if; 211 | 212 | end case; 213 | end process; 214 | 215 | sequential : process (clk) 216 | begin 217 | if rising_edge(clk) then 218 | -- ram processing 219 | if write_ram = '1' then 220 | ip_ram(write_addr) <= req_entry.ip; 221 | mac_ram(write_addr) <= req_entry.mac; 222 | end if; 223 | if next_read_addr < MAX_ARP_ENTRIES then 224 | arp_entry_val.ip <= ip_ram(next_read_addr); 225 | arp_entry_val.mac <= mac_ram(next_read_addr); 226 | else 227 | arp_entry_val.ip <= (others => '0'); 228 | arp_entry_val.mac <= (others => '0'); 229 | end if; 230 | 231 | read_result <= read_result_int; 232 | 233 | if reset = '1' or clear_store = '1' then 234 | -- reset state variables 235 | st_state <= IDLE; 236 | next_write_addr <= 0; 237 | num_entries <= 0; 238 | next_read_addr <= 0; 239 | entry_found.ip <= (others => '0'); 240 | entry_found.mac <= (others => '0'); 241 | req_entry.ip <= (others => '0'); 242 | req_entry.mac <= (others => '0'); 243 | mode <= MREAD; 244 | 245 | else 246 | -- Next req_state processing 247 | if set_st_state = '1' then 248 | st_state <= next_st_state; 249 | else 250 | st_state <= st_state; 251 | end if; 252 | 253 | -- mode setting and write request latching 254 | if set_mode = '1' then 255 | mode <= mode_val; 256 | if mode_val = MWRITE then 257 | req_entry <= write_req.entry; 258 | else 259 | req_entry.ip <= read_req.ip; 260 | req_entry.mac <= (others => '0'); 261 | end if; 262 | else 263 | mode <= mode; 264 | req_entry <= req_entry; 265 | end if; 266 | 267 | -- latch entry found 268 | if set_entry_found = '1' then 269 | entry_found <= arp_entry_val; 270 | else 271 | entry_found <= entry_found; 272 | end if; 273 | 274 | -- next_write_addr counts and wraps 275 | case set_next_write_addr is 276 | when HOLD => next_write_addr <= next_write_addr; 277 | when RST => next_write_addr <= 0; 278 | when INCR => if next_write_addr < MAX_ARP_ENTRIES-1 then next_write_addr <= next_write_addr + 1; else next_write_addr <= 0; end if; 279 | end case; 280 | 281 | -- num_entries counts and holds at max 282 | case set_num_entries is 283 | when HOLD => num_entries <= num_entries; 284 | when RST => num_entries <= 0; 285 | when INCR => if next_write_addr < MAX_ARP_ENTRIES then num_entries <= num_entries + 1; else num_entries <= num_entries; end if; 286 | end case; 287 | 288 | -- next_read_addr counts and wraps 289 | case set_next_read_addr is 290 | when HOLD => next_read_addr <= next_read_addr; 291 | when RST => next_read_addr <= 0; 292 | when INCR => if next_read_addr < MAX_ARP_ENTRIES then next_read_addr <= next_read_addr + 1; else next_read_addr <= 0; end if; 293 | end case; 294 | 295 | end if; 296 | end if; 297 | end process; 298 | 299 | end Behavioral; 300 | -------------------------------------------------------------------------------- /rtl/vhdl/ml605/IP_complete.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 20:25:56 06/03/2011 6 | -- Design Name: 7 | -- Module Name: IP_complete - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: Implements complete IP stack with ARP and MAC 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Additional Comments: 18 | -- 19 | ---------------------------------------------------------------------------------- 20 | LIBRARY ieee; 21 | USE ieee.std_logic_1164.ALL; 22 | use IEEE.NUMERIC_STD.ALL; 23 | use work.axi.all; 24 | use work.ipv4_types.all; 25 | use work.arp_types.all; 26 | 27 | entity IP_complete is 28 | generic ( 29 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 30 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 31 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 32 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 33 | ); 34 | Port ( 35 | -- IP Layer signals 36 | ip_tx_start : in std_logic; 37 | ip_tx : in ipv4_tx_type; -- IP tx cxns 38 | ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission) 39 | ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data 40 | ip_rx_start : out std_logic; -- indicates receipt of ip frame. 41 | ip_rx : out ipv4_rx_type; 42 | -- system signals 43 | clk_in_p : in std_logic; -- 200MHz clock input from board 44 | clk_in_n : in std_logic; 45 | clk_out : out std_logic; 46 | reset : in STD_LOGIC; 47 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 48 | our_mac_address : in std_logic_vector (47 downto 0); 49 | control : in ip_control_type; 50 | -- status signals 51 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 52 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 53 | -- GMII Interface 54 | phy_resetn : out std_logic; 55 | gmii_txd : out std_logic_vector(7 downto 0); 56 | gmii_tx_en : out std_logic; 57 | gmii_tx_er : out std_logic; 58 | gmii_tx_clk : out std_logic; 59 | gmii_rxd : in std_logic_vector(7 downto 0); 60 | gmii_rx_dv : in std_logic; 61 | gmii_rx_er : in std_logic; 62 | gmii_rx_clk : in std_logic; 63 | gmii_col : in std_logic; 64 | gmii_crs : in std_logic; 65 | mii_tx_clk : in std_logic 66 | ); 67 | end IP_complete; 68 | 69 | architecture structural of IP_complete is 70 | 71 | ------------------------------------------------------------------------------ 72 | -- Component Declaration for the IP layer 73 | ------------------------------------------------------------------------------ 74 | 75 | COMPONENT IP_complete_nomac 76 | generic ( 77 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 78 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 79 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 80 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 81 | ); 82 | Port ( 83 | -- IP Layer signals 84 | ip_tx_start : in std_logic; 85 | ip_tx : in ipv4_tx_type; -- IP tx cxns 86 | ip_tx_result : out std_logic_vector (1 downto 0); -- tx status (changes during transmission) 87 | ip_tx_data_out_ready : out std_logic; -- indicates IP TX is ready to take data 88 | ip_rx_start : out std_logic; -- indicates receipt of ip frame. 89 | ip_rx : out ipv4_rx_type; 90 | -- system signals 91 | rx_clk : in STD_LOGIC; 92 | tx_clk : in STD_LOGIC; 93 | reset : in STD_LOGIC; 94 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 95 | our_mac_address : in std_logic_vector (47 downto 0); 96 | control : in ip_control_type; 97 | -- status signals 98 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 99 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 100 | -- MAC Transmitter 101 | mac_tx_tdata : out std_logic_vector(7 downto 0); -- data byte to tx 102 | mac_tx_tvalid : out std_logic; -- tdata is valid 103 | mac_tx_tready : in std_logic; -- mac is ready to accept data 104 | mac_tx_tfirst : out std_logic; -- indicates first byte of frame 105 | mac_tx_tlast : out std_logic; -- indicates last byte of frame 106 | -- MAC Receiver 107 | mac_rx_tdata : in std_logic_vector(7 downto 0); -- data byte received 108 | mac_rx_tvalid : in std_logic; -- indicates tdata is valid 109 | mac_rx_tready : out std_logic; -- tells mac that we are ready to take data 110 | mac_rx_tlast : in std_logic -- indicates last byte of the trame 111 | ); 112 | END COMPONENT; 113 | 114 | 115 | ------------------------------------------------------------------------------ 116 | -- Component Declaration for the MAC layer 117 | ------------------------------------------------------------------------------ 118 | component mac_layer_v2_1 119 | port ( 120 | -- System controls 121 | ------------------ 122 | glbl_rst : in std_logic; -- asynchronous reset 123 | mac_reset : in std_logic; -- reset mac layer 124 | clk_in_p : in std_logic; -- 200MHz clock input from board 125 | clk_in_n : in std_logic; 126 | 127 | -- MAC Transmitter (AXI-S) Interface 128 | --------------------------------------------- 129 | mac_tx_clock : out std_logic; -- data sampled on rising edge 130 | mac_tx_tdata : in std_logic_vector(7 downto 0); -- data byte to tx 131 | mac_tx_tvalid : in std_logic; -- tdata is valid 132 | mac_tx_tready : out std_logic; -- mac is ready to accept data 133 | mac_tx_tlast : in std_logic; -- indicates last byte of frame 134 | 135 | -- MAC Receiver (AXI-S) Interface 136 | ------------------------------------------ 137 | mac_rx_clock : out std_logic; -- data valid on rising edge 138 | mac_rx_tdata : out std_logic_vector(7 downto 0); -- data byte received 139 | mac_rx_tvalid : out std_logic; -- indicates tdata is valid 140 | mac_rx_tready : in std_logic; -- tells mac that we are ready to take data 141 | mac_rx_tlast : out std_logic; -- indicates last byte of the trame 142 | 143 | -- GMII Interface 144 | ----------------- 145 | phy_resetn : out std_logic; 146 | gmii_txd : out std_logic_vector(7 downto 0); 147 | gmii_tx_en : out std_logic; 148 | gmii_tx_er : out std_logic; 149 | gmii_tx_clk : out std_logic; 150 | gmii_rxd : in std_logic_vector(7 downto 0); 151 | gmii_rx_dv : in std_logic; 152 | gmii_rx_er : in std_logic; 153 | gmii_rx_clk : in std_logic; 154 | gmii_col : in std_logic; 155 | gmii_crs : in std_logic; 156 | mii_tx_clk : in std_logic 157 | ); 158 | end component; 159 | 160 | --------------------------- 161 | -- Signals 162 | --------------------------- 163 | 164 | -- MAC RX bus 165 | signal mac_rx_clock : std_logic; 166 | signal mac_rx_tdata : std_logic_vector (7 downto 0); 167 | signal mac_rx_tvalid : std_logic; 168 | signal mac_rx_tready : std_logic; 169 | signal mac_rx_tlast : std_logic; 170 | -- MAC TX bus 171 | signal mac_tx_clock : std_logic; 172 | signal mac_tx_tdata : std_logic_vector (7 downto 0); 173 | signal mac_tx_tvalid : std_logic; 174 | signal mac_tx_tready : std_logic; 175 | signal mac_tx_tlast : std_logic; 176 | -- control signals 177 | signal mac_tx_tready_int : std_logic; 178 | signal mac_tx_granted_int : std_logic; 179 | 180 | begin 181 | 182 | clk_out <= mac_rx_clock; 183 | 184 | ------------------------------------------------------------------------------ 185 | -- Instantiate the IP layer 186 | ------------------------------------------------------------------------------ 187 | 188 | IP_layer : IP_complete_nomac 189 | generic map ( 190 | CLOCK_FREQ => CLOCK_FREQ, 191 | ARP_TIMEOUT => ARP_TIMEOUT, 192 | ARP_MAX_PKT_TMO => ARP_MAX_PKT_TMO, 193 | MAX_ARP_ENTRIES => MAX_ARP_ENTRIES 194 | ) 195 | PORT MAP ( 196 | -- IP Layer signals 197 | ip_tx_start => ip_tx_start, 198 | ip_tx => ip_tx, 199 | ip_tx_result => ip_tx_result, 200 | ip_tx_data_out_ready => ip_tx_data_out_ready, 201 | ip_rx_start => ip_rx_start, 202 | ip_rx => ip_rx, 203 | -- system signals 204 | rx_clk => mac_rx_clock, 205 | tx_clk => mac_rx_clock, 206 | reset => reset, 207 | our_ip_address => our_ip_address, 208 | our_mac_address => our_mac_address, 209 | control => control, 210 | -- status signals 211 | arp_pkt_count => arp_pkt_count, 212 | ip_pkt_count => ip_pkt_count, 213 | -- MAC Transmitter 214 | mac_tx_tready => mac_tx_tready_int, 215 | mac_tx_tvalid => mac_tx_tvalid, 216 | mac_tx_tfirst => open, 217 | mac_tx_tlast => mac_tx_tlast, 218 | mac_tx_tdata => mac_tx_tdata, 219 | -- MAC Receiver 220 | mac_rx_tdata => mac_rx_tdata, 221 | mac_rx_tvalid => mac_rx_tvalid, 222 | mac_rx_tready => mac_rx_tready, 223 | mac_rx_tlast => mac_rx_tlast 224 | ); 225 | 226 | 227 | ------------------------------------------------------------------------------ 228 | -- Instantiate the MAC layer 229 | ------------------------------------------------------------------------------ 230 | mac_block : mac_layer_v2_1 231 | Port map( 232 | -- System controls 233 | ------------------ 234 | glbl_rst => reset, 235 | mac_reset => '0', 236 | clk_in_p => clk_in_p, 237 | clk_in_n => clk_in_n, 238 | 239 | -- MAC Transmitter (AXI-S) Interface 240 | --------------------------------------------- 241 | mac_tx_clock => mac_tx_clock, 242 | mac_tx_tdata => mac_tx_tdata, 243 | mac_tx_tvalid => mac_tx_tvalid, 244 | mac_tx_tready => mac_tx_tready_int, 245 | mac_tx_tlast => mac_tx_tlast, 246 | 247 | -- MAC Receiver (AXI-S) Interface 248 | ------------------------------------------ 249 | mac_rx_clock => mac_rx_clock, 250 | mac_rx_tdata => mac_rx_tdata, 251 | mac_rx_tvalid => mac_rx_tvalid, 252 | mac_rx_tready => mac_rx_tready, 253 | mac_rx_tlast => mac_rx_tlast, 254 | 255 | -- GMII Interface 256 | ----------------- 257 | phy_resetn => phy_resetn, 258 | gmii_txd => gmii_txd, 259 | gmii_tx_en => gmii_tx_en, 260 | gmii_tx_er => gmii_tx_er, 261 | gmii_tx_clk => gmii_tx_clk, 262 | gmii_rxd => gmii_rxd, 263 | gmii_rx_dv => gmii_rx_dv, 264 | gmii_rx_er => gmii_rx_er, 265 | gmii_rx_clk => gmii_rx_clk, 266 | gmii_col => gmii_col, 267 | gmii_crs => gmii_crs, 268 | mii_tx_clk => mii_tx_clk 269 | ); 270 | 271 | end structural; 272 | 273 | -------------------------------------------------------------------------------- /rtl/vhdl/UDP_TX.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 5 June 2011 6 | -- Design Name: 7 | -- Module Name: UDP_TX - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle simple UDP TX 13 | -- doesnt generate the checksum(supposedly optional) 14 | -- Dependencies: 15 | -- 16 | -- Revision: 17 | -- Revision 0.01 - File Created 18 | -- Revision 0.02 - Added abort of tx when receive last from upstream 19 | -- Additional Comments: 20 | -- 21 | ---------------------------------------------------------------------------------- 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.ALL; 24 | use IEEE.NUMERIC_STD.ALL; 25 | use work.axi.all; 26 | use work.ipv4_types.all; 27 | 28 | entity UDP_TX is 29 | Port ( 30 | -- UDP Layer signals 31 | udp_tx_start : in std_logic; -- indicates req to tx UDP 32 | udp_txi : in udp_tx_type; -- UDP tx cxns 33 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 34 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 35 | -- system signals 36 | clk : in STD_LOGIC; -- same clock used to clock mac data and ip data 37 | reset : in STD_LOGIC; 38 | -- IP layer TX signals 39 | ip_tx_start : out std_logic; 40 | ip_tx : out ipv4_tx_type; -- IP tx cxns 41 | ip_tx_result : in std_logic_vector (1 downto 0); -- tx status (changes during transmission) 42 | ip_tx_data_out_ready : in std_logic -- indicates IP TX is ready to take data 43 | ); 44 | end UDP_TX; 45 | 46 | architecture Behavioral of UDP_TX is 47 | type tx_state_type is (IDLE, PAUSE, SEND_UDP_HDR, SEND_USER_DATA); 48 | 49 | type count_mode_type is (RST, INCR, HOLD); 50 | type settable_cnt_type is (RST, SET, INCR, HOLD); 51 | type set_clr_type is (SET, CLR, HOLD); 52 | 53 | -- TX state variables 54 | signal udp_tx_state : tx_state_type; 55 | signal tx_count : unsigned (15 downto 0); 56 | signal tx_result_reg : std_logic_vector (1 downto 0); 57 | signal ip_tx_start_reg : std_logic; 58 | signal data_out_ready_reg : std_logic; 59 | 60 | -- tx control signals 61 | signal next_tx_state : tx_state_type; 62 | signal set_tx_state : std_logic; 63 | signal next_tx_result : std_logic_vector (1 downto 0); 64 | signal set_tx_result : std_logic; 65 | signal tx_count_val : unsigned (15 downto 0); 66 | signal tx_count_mode : settable_cnt_type; 67 | signal tx_data : std_logic_vector (7 downto 0); 68 | signal set_last : std_logic; 69 | signal set_ip_tx_start : set_clr_type; 70 | signal tx_data_valid : std_logic; -- indicates whether data is valid to tx or not 71 | 72 | -- tx temp signals 73 | signal total_length : std_logic_vector (15 downto 0); -- computed combinatorially from header size 74 | 75 | 76 | -- IP datagram header format 77 | -- 78 | -- 0 4 8 16 19 24 31 79 | -- -------------------------------------------------------------------------------------------- 80 | -- | source port number | dest port number | 81 | -- | | | 82 | -- -------------------------------------------------------------------------------------------- 83 | -- | length (bytes) | checksum | 84 | -- | (header and data combined) | | 85 | -- -------------------------------------------------------------------------------------------- 86 | -- | Data | 87 | -- | | 88 | -- -------------------------------------------------------------------------------------------- 89 | -- | .... | 90 | -- | | 91 | -- -------------------------------------------------------------------------------------------- 92 | 93 | begin 94 | ----------------------------------------------------------------------- 95 | -- combinatorial process to implement FSM and determine control signals 96 | ----------------------------------------------------------------------- 97 | 98 | tx_combinatorial : process( 99 | -- input signals 100 | udp_tx_start, udp_txi, clk, ip_tx_result, ip_tx_data_out_ready, 101 | -- state variables 102 | udp_tx_state, tx_count, tx_result_reg, ip_tx_start_reg, data_out_ready_reg, 103 | -- control signals 104 | next_tx_state, set_tx_state, next_tx_result, set_tx_result, tx_count_mode, tx_count_val, 105 | tx_data, set_last, total_length, set_ip_tx_start, tx_data_valid 106 | ) 107 | 108 | begin 109 | -- set output followers 110 | ip_tx_start <= ip_tx_start_reg; 111 | ip_tx.hdr.protocol <= x"11"; -- UDP protocol 112 | ip_tx.hdr.data_length <= total_length; 113 | ip_tx.hdr.dst_ip_addr <= udp_txi.hdr.dst_ip_addr; 114 | if udp_tx_start = '1' and ip_tx_start_reg = '0' then 115 | udp_tx_result <= UDPTX_RESULT_NONE; -- kill the result until have started the IP layer 116 | else 117 | udp_tx_result <= tx_result_reg; 118 | end if; 119 | 120 | case udp_tx_state is 121 | when SEND_USER_DATA => 122 | ip_tx.data.data_out <= udp_txi.data.data_out; 123 | tx_data_valid <= udp_txi.data.data_out_valid; 124 | ip_tx.data.data_out_last <= udp_txi.data.data_out_last; 125 | 126 | when SEND_UDP_HDR => 127 | ip_tx.data.data_out <= tx_data; 128 | tx_data_valid <= ip_tx_data_out_ready; 129 | ip_tx.data.data_out_last <= set_last; 130 | 131 | when others => 132 | ip_tx.data.data_out <= (others => '0'); 133 | tx_data_valid <= '0'; 134 | ip_tx.data.data_out_last <= set_last; 135 | end case; 136 | 137 | ip_tx.data.data_out_valid <= tx_data_valid and ip_tx_data_out_ready; 138 | 139 | -- set signal defaults 140 | next_tx_state <= IDLE; 141 | set_tx_state <= '0'; 142 | tx_count_mode <= HOLD; 143 | tx_data <= x"00"; 144 | set_last <= '0'; 145 | next_tx_result <= UDPTX_RESULT_NONE; 146 | set_tx_result <= '0'; 147 | set_ip_tx_start <= HOLD; 148 | tx_count_val <= (others => '0'); 149 | udp_tx_data_out_ready <= '0'; 150 | 151 | -- set temp signals 152 | total_length <= std_logic_vector(unsigned(udp_txi.hdr.data_length) + 8); -- total length = user data length + header length (bytes) 153 | 154 | -- TX FSM 155 | case udp_tx_state is 156 | when IDLE => 157 | udp_tx_data_out_ready <= '0'; -- in this state, we are unable to accept user data for tx 158 | tx_count_mode <= RST; 159 | if udp_tx_start = '1' then 160 | -- check header count for error if too high 161 | if unsigned(udp_txi.hdr.data_length) > 1472 then 162 | next_tx_result <= UDPTX_RESULT_ERR; 163 | set_tx_result <= '1'; 164 | else 165 | -- start to send UDP header 166 | tx_count_mode <= RST; 167 | next_tx_result <= UDPTX_RESULT_SENDING; 168 | set_ip_tx_start <= SET; 169 | set_tx_result <= '1'; 170 | next_tx_state <= PAUSE; 171 | set_tx_state <= '1'; 172 | end if; 173 | end if; 174 | 175 | when PAUSE => 176 | -- delay one clock for IP layer to respond to ip_tx_start and remove any tx error result 177 | next_tx_state <= SEND_UDP_HDR; 178 | set_tx_state <= '1'; 179 | 180 | when SEND_UDP_HDR => 181 | udp_tx_data_out_ready <= '0'; -- in this state, we are unable to accept user data for tx 182 | if ip_tx_result = IPTX_RESULT_ERR then 183 | set_ip_tx_start <= CLR; 184 | next_tx_result <= UDPTX_RESULT_ERR; 185 | set_tx_result <= '1'; 186 | next_tx_state <= IDLE; 187 | set_tx_state <= '1'; 188 | elsif ip_tx_data_out_ready = '1' then 189 | if tx_count = x"0007" then 190 | tx_count_val <= x"0001"; 191 | tx_count_mode <= SET; 192 | next_tx_state <= SEND_USER_DATA; 193 | set_tx_state <= '1'; 194 | else 195 | tx_count_mode <= INCR; 196 | end if; 197 | case tx_count is 198 | when x"0000" => tx_data <= udp_txi.hdr.src_port (15 downto 8); -- src port 199 | when x"0001" => tx_data <= udp_txi.hdr.src_port (7 downto 0); 200 | when x"0002" => tx_data <= udp_txi.hdr.dst_port (15 downto 8); -- dst port 201 | when x"0003" => tx_data <= udp_txi.hdr.dst_port (7 downto 0); 202 | when x"0004" => tx_data <= total_length (15 downto 8); -- length 203 | when x"0005" => tx_data <= total_length (7 downto 0); 204 | when x"0006" => tx_data <= udp_txi.hdr.checksum (15 downto 8); -- checksum (set by upstream) 205 | when x"0007" => tx_data <= udp_txi.hdr.checksum (7 downto 0); 206 | when others => 207 | -- shouldnt get here - handle as error 208 | next_tx_result <= UDPTX_RESULT_ERR; 209 | set_tx_result <= '1'; 210 | end case; 211 | end if; 212 | 213 | when SEND_USER_DATA => 214 | udp_tx_data_out_ready <= ip_tx_data_out_ready; -- in this state, we can accept user data if IP TX rdy 215 | if ip_tx_data_out_ready = '1' then 216 | if udp_txi.data.data_out_valid = '1' or tx_count = x"000" then 217 | -- only increment if ready and valid has been subsequently established, otherwise data count moves on too fast 218 | if unsigned(tx_count) = unsigned(udp_txi.hdr.data_length) then 219 | -- TX terminated due to count - end normally 220 | set_last <= '1'; 221 | tx_data <= udp_txi.data.data_out; 222 | next_tx_result <= UDPTX_RESULT_SENT; 223 | set_ip_tx_start <= CLR; 224 | set_tx_result <= '1'; 225 | next_tx_state <= IDLE; 226 | set_tx_state <= '1'; 227 | elsif udp_txi.data.data_out_last = '1' then 228 | -- terminate tx with error as got last from upstream before exhausting count 229 | set_last <= '1'; 230 | tx_data <= udp_txi.data.data_out; 231 | next_tx_result <= UDPTX_RESULT_ERR; 232 | set_ip_tx_start <= CLR; 233 | set_tx_result <= '1'; 234 | next_tx_state <= IDLE; 235 | set_tx_state <= '1'; 236 | else 237 | -- TX continues 238 | tx_count_mode <= INCR; 239 | tx_data <= udp_txi.data.data_out; 240 | end if; 241 | end if; 242 | end if; 243 | 244 | end case; 245 | end process; 246 | 247 | ----------------------------------------------------------------------------- 248 | -- sequential process to action control signals and change states and outputs 249 | ----------------------------------------------------------------------------- 250 | 251 | tx_sequential : process (clk,reset,data_out_ready_reg) 252 | begin 253 | if rising_edge(clk) then 254 | data_out_ready_reg <= ip_tx_data_out_ready; 255 | else 256 | data_out_ready_reg <= data_out_ready_reg; 257 | end if; 258 | 259 | if rising_edge(clk) then 260 | if reset = '1' then 261 | -- reset state variables 262 | udp_tx_state <= IDLE; 263 | tx_count <= x"0000"; 264 | tx_result_reg <= IPTX_RESULT_NONE; 265 | ip_tx_start_reg <= '0'; 266 | else 267 | -- Next udp_tx_state processing 268 | if set_tx_state = '1' then 269 | udp_tx_state <= next_tx_state; 270 | else 271 | udp_tx_state <= udp_tx_state; 272 | end if; 273 | 274 | -- ip_tx_start_reg processing 275 | case set_ip_tx_start is 276 | when SET => ip_tx_start_reg <= '1'; 277 | when CLR => ip_tx_start_reg <= '0'; 278 | when HOLD => ip_tx_start_reg <= ip_tx_start_reg; 279 | end case; 280 | 281 | -- tx result processing 282 | if set_tx_result = '1' then 283 | tx_result_reg <= next_tx_result; 284 | else 285 | tx_result_reg <= tx_result_reg; 286 | end if; 287 | 288 | -- tx_count processing 289 | case tx_count_mode is 290 | when RST => tx_count <= x"0000"; 291 | when SET => tx_count <= tx_count_val; 292 | when INCR => tx_count <= tx_count + 1; 293 | when HOLD => tx_count <= tx_count; 294 | end case; 295 | 296 | end if; 297 | end if; 298 | end process; 299 | 300 | 301 | end Behavioral; 302 | 303 | -------------------------------------------------------------------------------- /rtl/vhdl/ml605/UDP_Complete.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 17:51:18 06/11/2011 6 | -- Design Name: 7 | -- Module Name: UDP_Complete - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Revision 0.02 - separated RX and TX clocks 18 | -- Additional Comments: 19 | -- 20 | ---------------------------------------------------------------------------------- 21 | library IEEE; 22 | use IEEE.STD_LOGIC_1164.ALL; 23 | use IEEE.NUMERIC_STD.ALL; 24 | use work.axi.all; 25 | use work.ipv4_types.all; 26 | use work.arp_types.all; 27 | 28 | entity UDP_Complete is 29 | generic ( 30 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 31 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 32 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 33 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 34 | ); 35 | Port ( 36 | -- UDP TX signals 37 | udp_tx_start : in std_logic; -- indicates req to tx UDP 38 | udp_txi : in udp_tx_type; -- UDP tx cxns 39 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 40 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 41 | -- UDP RX signals 42 | udp_rx_start : out std_logic; -- indicates receipt of udp header 43 | udp_rxo : out udp_rx_type; 44 | -- IP RX signals 45 | ip_rx_hdr : out ipv4_rx_header_type; 46 | -- system signals 47 | clk_in_p : in std_logic; -- 200MHz clock input from board 48 | clk_in_n : in std_logic; 49 | clk_out : out std_logic; 50 | reset : in STD_LOGIC; 51 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 52 | our_mac_address : in std_logic_vector (47 downto 0); 53 | control : in udp_control_type; 54 | -- status signals 55 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 56 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 57 | -- GMII Interface 58 | phy_resetn : out std_logic; 59 | gmii_txd : out std_logic_vector(7 downto 0); 60 | gmii_tx_en : out std_logic; 61 | gmii_tx_er : out std_logic; 62 | gmii_tx_clk : out std_logic; 63 | gmii_rxd : in std_logic_vector(7 downto 0); 64 | gmii_rx_dv : in std_logic; 65 | gmii_rx_er : in std_logic; 66 | gmii_rx_clk : in std_logic; 67 | gmii_col : in std_logic; 68 | gmii_crs : in std_logic; 69 | mii_tx_clk : in std_logic 70 | ); 71 | end UDP_Complete; 72 | 73 | 74 | 75 | 76 | architecture structural of UDP_Complete is 77 | 78 | ------------------------------------------------------------------------------ 79 | -- Component Declaration for UDP complete no mac 80 | ------------------------------------------------------------------------------ 81 | 82 | COMPONENT UDP_Complete_nomac 83 | generic ( 84 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 85 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 86 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 87 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the ARP store 88 | ); 89 | Port ( 90 | -- UDP TX signals 91 | udp_tx_start : in std_logic; -- indicates req to tx UDP 92 | udp_txi : in udp_tx_type; -- UDP tx cxns 93 | udp_tx_result : out std_logic_vector (1 downto 0);-- tx status (changes during transmission) 94 | udp_tx_data_out_ready: out std_logic; -- indicates udp_tx is ready to take data 95 | -- UDP RX signals 96 | udp_rx_start : out std_logic; -- indicates receipt of udp header 97 | udp_rxo : out udp_rx_type; 98 | -- IP RX signals 99 | ip_rx_hdr : out ipv4_rx_header_type; 100 | -- system signals 101 | rx_clk : in STD_LOGIC; 102 | tx_clk : in STD_LOGIC; 103 | reset : in STD_LOGIC; 104 | our_ip_address : in STD_LOGIC_VECTOR (31 downto 0); 105 | our_mac_address : in std_logic_vector (47 downto 0); 106 | control : in udp_control_type; 107 | -- status signals 108 | arp_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- count of arp pkts received 109 | ip_pkt_count : out STD_LOGIC_VECTOR(7 downto 0); -- number of IP pkts received for us 110 | -- MAC Transmitter 111 | mac_tx_tdata : out std_logic_vector(7 downto 0); -- data byte to tx 112 | mac_tx_tvalid : out std_logic; -- tdata is valid 113 | mac_tx_tready : in std_logic; -- mac is ready to accept data 114 | mac_tx_tfirst : out std_logic; -- indicates first byte of frame 115 | mac_tx_tlast : out std_logic; -- indicates last byte of frame 116 | -- MAC Receiver 117 | mac_rx_tdata : in std_logic_vector(7 downto 0); -- data byte received 118 | mac_rx_tvalid : in std_logic; -- indicates tdata is valid 119 | mac_rx_tready : out std_logic; -- tells mac that we are ready to take data 120 | mac_rx_tlast : in std_logic -- indicates last byte of the trame 121 | ); 122 | END COMPONENT; 123 | 124 | 125 | ------------------------------------------------------------------------------ 126 | -- Component Declaration for the MAC layer 127 | ------------------------------------------------------------------------------ 128 | component mac_v2_2 129 | -- component xv6mac_straight 130 | port ( 131 | -- System controls 132 | ------------------ 133 | glbl_rst : in std_logic; -- asynchronous reset 134 | mac_reset : in std_logic; -- reset mac layer 135 | clk_in_p : in std_logic; -- 200MHz clock input from board 136 | clk_in_n : in std_logic; 137 | 138 | -- MAC Transmitter (AXI-S) Interface 139 | --------------------------------------------- 140 | mac_tx_clock : out std_logic; -- data sampled on rising edge 141 | mac_tx_tdata : in std_logic_vector(7 downto 0); -- data byte to tx 142 | mac_tx_tvalid : in std_logic; -- tdata is valid 143 | mac_tx_tready : out std_logic; -- mac is ready to accept data 144 | mac_tx_tlast : in std_logic; -- indicates last byte of frame 145 | 146 | -- MAC Receiver (AXI-S) Interface 147 | ------------------------------------------ 148 | mac_rx_clock : out std_logic; -- data valid on rising edge 149 | mac_rx_tdata : out std_logic_vector(7 downto 0); -- data byte received 150 | mac_rx_tvalid : out std_logic; -- indicates tdata is valid 151 | mac_rx_tready : in std_logic; -- tells mac that we are ready to take data 152 | mac_rx_tlast : out std_logic; -- indicates last byte of the trame 153 | 154 | -- GMII Interface 155 | ----------------- 156 | phy_resetn : out std_logic; 157 | gmii_txd : out std_logic_vector(7 downto 0); 158 | gmii_tx_en : out std_logic; 159 | gmii_tx_er : out std_logic; 160 | gmii_tx_clk : out std_logic; 161 | gmii_rxd : in std_logic_vector(7 downto 0); 162 | gmii_rx_dv : in std_logic; 163 | gmii_rx_er : in std_logic; 164 | gmii_rx_clk : in std_logic; 165 | gmii_col : in std_logic; 166 | gmii_crs : in std_logic; 167 | mii_tx_clk : in std_logic 168 | ); 169 | end component; 170 | 171 | 172 | --------------------------- 173 | -- Signals 174 | --------------------------- 175 | 176 | -- MAC RX bus 177 | signal mac_rx_clock : std_logic; 178 | signal mac_rx_tdata : std_logic_vector (7 downto 0); 179 | signal mac_rx_tvalid : std_logic; 180 | signal mac_rx_tready : std_logic; 181 | signal mac_rx_tlast : std_logic; 182 | -- MAC TX bus 183 | signal mac_tx_clock : std_logic; 184 | signal mac_tx_tdata : std_logic_vector (7 downto 0); 185 | signal mac_tx_tvalid : std_logic; 186 | signal mac_tx_tready : std_logic; 187 | signal mac_tx_tlast : std_logic; 188 | -- control signals 189 | signal mac_tx_tready_int : std_logic; 190 | signal mac_tx_granted_int : std_logic; 191 | 192 | 193 | begin 194 | 195 | 196 | process (mac_tx_clock) 197 | begin 198 | -- output followers 199 | clk_out <= mac_tx_clock; 200 | end process; 201 | 202 | ------------------------------------------------------------------------------ 203 | -- Instantiate the UDP layer 204 | ------------------------------------------------------------------------------ 205 | 206 | udp_block: UDP_Complete_nomac 207 | generic map ( 208 | CLOCK_FREQ => CLOCK_FREQ, 209 | ARP_TIMEOUT => ARP_TIMEOUT, 210 | ARP_MAX_PKT_TMO => ARP_MAX_PKT_TMO, 211 | MAX_ARP_ENTRIES => MAX_ARP_ENTRIES 212 | ) 213 | PORT MAP ( 214 | -- UDP TX signals 215 | udp_tx_start => udp_tx_start, 216 | udp_txi => udp_txi, 217 | udp_tx_result => udp_tx_result, 218 | udp_tx_data_out_ready => udp_tx_data_out_ready, 219 | -- UDP RX signals 220 | udp_rx_start => udp_rx_start, 221 | udp_rxo => udp_rxo, 222 | -- IP RX signals 223 | ip_rx_hdr => ip_rx_hdr, 224 | -- system signals 225 | rx_clk => mac_rx_clock, 226 | tx_clk => mac_tx_clock, 227 | reset => reset, 228 | our_ip_address => our_ip_address, 229 | our_mac_address => our_mac_address, 230 | -- status signals 231 | arp_pkt_count => arp_pkt_count, 232 | ip_pkt_count => ip_pkt_count, 233 | control => control, 234 | -- MAC Transmitter 235 | mac_tx_tready => mac_tx_tready_int, 236 | mac_tx_tvalid => mac_tx_tvalid, 237 | mac_tx_tfirst => open, 238 | mac_tx_tlast => mac_tx_tlast, 239 | mac_tx_tdata => mac_tx_tdata, 240 | -- MAC Receiver 241 | mac_rx_tdata => mac_rx_tdata, 242 | mac_rx_tvalid => mac_rx_tvalid, 243 | mac_rx_tready => mac_rx_tready, 244 | mac_rx_tlast => mac_rx_tlast 245 | ); 246 | 247 | 248 | ------------------------------------------------------------------------------ 249 | -- Instantiate the MAC layer 250 | ------------------------------------------------------------------------------ 251 | mac_block : mac_v2_2 252 | -- mac_block : xv6mac_straight 253 | Port map( 254 | -- System controls 255 | ------------------ 256 | glbl_rst => reset, 257 | mac_reset => '0', 258 | clk_in_p => clk_in_p, 259 | clk_in_n => clk_in_n, 260 | 261 | -- MAC Transmitter (AXI-S) Interface 262 | --------------------------------------------- 263 | mac_tx_clock => mac_tx_clock, 264 | mac_tx_tdata => mac_tx_tdata, 265 | mac_tx_tvalid => mac_tx_tvalid, 266 | mac_tx_tready => mac_tx_tready_int, 267 | mac_tx_tlast => mac_tx_tlast, 268 | 269 | -- MAC Receiver (AXI-S) Interface 270 | ------------------------------------------ 271 | mac_rx_clock => mac_rx_clock, 272 | mac_rx_tdata => mac_rx_tdata, 273 | mac_rx_tvalid => mac_rx_tvalid, 274 | mac_rx_tready => mac_rx_tready, 275 | mac_rx_tlast => mac_rx_tlast, 276 | 277 | -- GMII Interface 278 | ----------------- 279 | phy_resetn => phy_resetn, 280 | gmii_txd => gmii_txd, 281 | gmii_tx_en => gmii_tx_en, 282 | gmii_tx_er => gmii_tx_er, 283 | gmii_tx_clk => gmii_tx_clk, 284 | gmii_rxd => gmii_rxd, 285 | gmii_rx_dv => gmii_rx_dv, 286 | gmii_rx_er => gmii_rx_er, 287 | gmii_rx_clk => gmii_rx_clk, 288 | gmii_col => gmii_col, 289 | gmii_crs => gmii_crs, 290 | mii_tx_clk => mii_tx_clk 291 | ); 292 | 293 | 294 | end structural; 295 | 296 | 297 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_REQ.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 12:00:04 05/31/2011 6 | -- Design Name: 7 | -- Module Name: arp_REQ - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle requests for ARP resolution 13 | -- responds from single entry cache or searches external arp store, or asks to send a request 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created from arp.vhd 0.2 19 | -- Additional Comments: 20 | -- 21 | ---------------------------------------------------------------------------------- 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.all; 24 | use IEEE.NUMERIC_STD.all; 25 | use work.arp_types.all; 26 | 27 | entity arp_req is 28 | generic ( 29 | no_default_gateway : boolean := true; -- set to false if communicating with devices accessed 30 | -- through a "default gateway or router" 31 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 32 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 33 | ARP_MAX_PKT_TMO : integer := 5 -- # wrong nwk pkts received before set error 34 | ); 35 | port ( 36 | -- lookup request signals 37 | arp_req_req : in arp_req_req_type; -- request for a translation from IP to MAC 38 | arp_req_rslt : out arp_req_rslt_type; -- the result 39 | -- external arp store signals 40 | arp_store_req : out arp_store_rdrequest_t; -- requesting a lookup or store 41 | arp_store_result : in arp_store_result_t; -- the result 42 | -- network request signals 43 | arp_nwk_req : out arp_nwk_request_t; -- requesting resolution via the network 44 | arp_nwk_result : in arp_nwk_result_t; -- the result 45 | -- system signals 46 | clear_cache : in std_logic; -- clear the internal cache 47 | nwk_gateway : in std_logic_vector(31 downto 0); -- IP address of default gateway 48 | nwk_mask : in std_logic_vector(31 downto 0); -- Net mask 49 | clk : in std_logic; 50 | reset : in std_logic 51 | ); 52 | end arp_req; 53 | 54 | architecture Behavioral of arp_req is 55 | 56 | type req_state_t is (IDLE, LOOKUP, WAIT_REPLY, PAUSE1, PAUSE2, PAUSE3); 57 | type set_cntr_t is (HOLD, CLR, INCR); 58 | type set_clr_type is (SET, CLR, HOLD); 59 | 60 | -- state variables 61 | signal req_state : req_state_t; 62 | signal req_ip_addr : std_logic_vector (31 downto 0); -- IP address to lookup 63 | signal arp_entry_cache : arp_entry_t; -- single entry cache for fast response 64 | signal cache_valid : std_logic; -- single entry cache is valid 65 | signal nwk_rx_cntr : unsigned(7 downto 0); -- counts nwk rx pkts that dont satisfy 66 | signal freq_scaler : unsigned (31 downto 0); -- scales data_in_clk downto 1Hz 67 | signal timer : unsigned (7 downto 0); -- counts seconds timeout 68 | signal timeout_reg : std_logic; 69 | 70 | -- busses 71 | signal next_req_state : req_state_t; 72 | signal arp_entry_val : arp_entry_t; 73 | 74 | -- requester control signals 75 | signal set_req_state : std_logic; 76 | signal set_req_ip : std_logic; 77 | signal store_arp_cache : std_logic; 78 | signal set_nwk_rx_cntr : set_cntr_t; 79 | signal set_timer : set_cntr_t; -- timer reset, count, hold control 80 | signal timer_enable : std_logic; -- enable the timer counting 81 | signal set_timeout : set_clr_type; -- control the timeout register 82 | signal clear_cache_valid : std_logic; 83 | 84 | signal l_arp_req_req_ip : std_logic_vector(31 downto 0); -- local network IP address for resolution 85 | 86 | begin 87 | 88 | default_GW: if (not no_default_gateway) generate 89 | default_gw_comb_p: process (arp_req_req.ip, nwk_gateway, nwk_mask) is 90 | begin -- process default_gw_comb_p 91 | -- translate IP addresses to local IP address if necessary 92 | if ((nwk_mask and arp_req_req.ip) = (nwk_mask and nwk_gateway)) then 93 | -- on local network 94 | l_arp_req_req_ip <= arp_req_req.ip; 95 | else 96 | -- on remote network 97 | l_arp_req_req_ip <= nwk_gateway; 98 | end if; 99 | end process default_gw_comb_p; 100 | end generate default_GW; 101 | 102 | no_default_GW: if (no_default_gateway) generate 103 | no_default_gw_comb_p: process (arp_req_req.ip) is 104 | begin -- process no_default_gw_comb_p 105 | l_arp_req_req_ip <= arp_req_req.ip; 106 | end process no_default_gw_comb_p; 107 | end generate no_default_GW; 108 | 109 | req_combinatorial : process ( 110 | arp_entry_cache.ip, arp_entry_cache.mac, arp_nwk_result.entry, arp_nwk_result.entry.ip, 111 | arp_nwk_result.entry.mac, arp_nwk_result.status, arp_req_req.lookup_req, 112 | arp_store_result.entry, arp_store_result.entry.mac, arp_store_result.status, cache_valid, 113 | clear_cache, freq_scaler, l_arp_req_req_ip, nwk_rx_cntr, req_ip_addr, req_state, 114 | timeout_reg, timer) 115 | begin 116 | -- set output followers 117 | arp_req_rslt.got_mac <= '0'; -- set initial value of request result outputs 118 | arp_req_rslt.got_err <= '0'; 119 | arp_req_rslt.mac <= (others => '0'); 120 | arp_store_req.req <= '0'; 121 | arp_store_req.ip <= (others => '0'); 122 | arp_nwk_req.req <= '0'; 123 | arp_nwk_req.ip <= (others => '0'); 124 | 125 | -- zero time response to lookup request if already in cache 126 | if arp_req_req.lookup_req = '1' and l_arp_req_req_ip = arp_entry_cache.ip and cache_valid = '1' then 127 | arp_req_rslt.got_mac <= '1'; 128 | arp_req_rslt.mac <= arp_entry_cache.mac; 129 | elsif arp_req_req.lookup_req = '1' then 130 | -- hold off got_mac while req is there as arp_entry will not be correct yet 131 | arp_req_rslt.got_mac <= '0'; 132 | arp_req_rslt.mac <= arp_entry_cache.mac; 133 | else 134 | arp_req_rslt.got_mac <= cache_valid; 135 | arp_req_rslt.mac <= arp_entry_cache.mac; 136 | end if; 137 | 138 | if arp_req_req.lookup_req = '1' then 139 | -- ensure any existing error report is killed at the start of a request 140 | arp_req_rslt.got_err <= '0'; 141 | else 142 | arp_req_rslt.got_err <= timeout_reg; 143 | end if; 144 | 145 | -- set signal defaults 146 | next_req_state <= IDLE; 147 | set_req_state <= '0'; 148 | set_req_ip <= '0'; 149 | store_arp_cache <= '0'; 150 | arp_entry_val.ip <= (others => '0'); 151 | arp_entry_val.mac <= (others => '0'); 152 | set_nwk_rx_cntr <= HOLD; 153 | set_timer <= INCR; -- default is timer running, unless we hold or reset it 154 | set_timeout <= HOLD; 155 | timer_enable <= '0'; 156 | clear_cache_valid <= clear_cache; 157 | 158 | -- combinatorial logic 159 | if freq_scaler = x"00000000" then 160 | timer_enable <= '1'; 161 | end if; 162 | 163 | -- REQ FSM 164 | case req_state is 165 | when IDLE => 166 | set_timer <= CLR; 167 | if arp_req_req.lookup_req = '1' then 168 | -- check if we already have the info in cache 169 | if l_arp_req_req_ip = arp_entry_cache.ip and cache_valid = '1' then 170 | -- already have this IP - feed output back 171 | arp_req_rslt.got_mac <= '1'; 172 | arp_req_rslt.mac <= arp_entry_cache.mac; 173 | else 174 | clear_cache_valid <= '1'; -- remove cache entry 175 | set_timeout <= CLR; 176 | next_req_state <= LOOKUP; 177 | set_req_state <= '1'; 178 | set_req_ip <= '1'; 179 | end if; 180 | end if; 181 | 182 | when LOOKUP => 183 | -- put request on the store 184 | arp_store_req.ip <= req_ip_addr; 185 | arp_store_req.req <= '1'; 186 | case arp_store_result.status is 187 | when FOUND => 188 | -- update the cache 189 | arp_entry_val <= arp_store_result.entry; 190 | store_arp_cache <= '1'; 191 | -- and feed output back 192 | arp_req_rslt.got_mac <= '1'; 193 | arp_req_rslt.mac <= arp_store_result.entry.mac; 194 | next_req_state <= IDLE; 195 | set_req_state <= '1'; 196 | 197 | when NOT_FOUND => 198 | -- need to request from the network 199 | set_timer <= CLR; 200 | set_nwk_rx_cntr <= CLR; 201 | arp_nwk_req.req <= '1'; 202 | arp_nwk_req.ip <= req_ip_addr; 203 | next_req_state <= WAIT_REPLY; 204 | set_req_state <= '1'; 205 | 206 | when others => 207 | -- just keep waiting - no timeout (assumes lookup with either succeed or fail) 208 | end case; 209 | 210 | when WAIT_REPLY => 211 | case arp_nwk_result.status is 212 | when RECEIVED => 213 | if arp_nwk_result.entry.ip = req_ip_addr then 214 | -- store into cache 215 | arp_entry_val <= arp_nwk_result.entry; 216 | store_arp_cache <= '1'; 217 | -- and feed output back 218 | arp_req_rslt.got_mac <= '1'; 219 | arp_req_rslt.mac <= arp_nwk_result.entry.mac; 220 | next_req_state <= IDLE; 221 | set_req_state <= '1'; 222 | else 223 | if nwk_rx_cntr > ARP_MAX_PKT_TMO then 224 | set_timeout <= SET; 225 | next_req_state <= IDLE; 226 | set_req_state <= '1'; 227 | else 228 | set_nwk_rx_cntr <= INCR; 229 | end if; 230 | end if; 231 | 232 | when error => 233 | set_timeout <= SET; 234 | 235 | when others => 236 | if timer >= ARP_TIMEOUT then 237 | set_timeout <= SET; 238 | next_req_state <= PAUSE1; 239 | set_req_state <= '1'; 240 | end if; 241 | end case; 242 | 243 | when PAUSE1 => 244 | next_req_state <= PAUSE2; 245 | set_req_state <= '1'; 246 | 247 | when PAUSE2 => 248 | next_req_state <= PAUSE3; 249 | set_req_state <= '1'; 250 | 251 | when PAUSE3 => 252 | next_req_state <= IDLE; 253 | set_req_state <= '1'; 254 | 255 | end case; 256 | end process; 257 | 258 | req_sequential : process (clk) 259 | begin 260 | if rising_edge(clk) then 261 | if reset = '1' then 262 | -- reset state variables 263 | req_state <= IDLE; 264 | req_ip_addr <= (others => '0'); 265 | arp_entry_cache.ip <= (others => '0'); 266 | arp_entry_cache.mac <= (others => '0'); 267 | cache_valid <= '0'; 268 | nwk_rx_cntr <= (others => '0'); 269 | freq_scaler <= to_unsigned(CLOCK_FREQ, 32); 270 | timer <= (others => '0'); 271 | timeout_reg <= '0'; 272 | else 273 | -- Next req_state processing 274 | if set_req_state = '1' then 275 | req_state <= next_req_state; 276 | else 277 | req_state <= req_state; 278 | end if; 279 | 280 | -- Latch the requested IP address 281 | if set_req_ip = '1' then 282 | req_ip_addr <= l_arp_req_req_ip; 283 | else 284 | req_ip_addr <= req_ip_addr; 285 | end if; 286 | 287 | -- network received counter 288 | case set_nwk_rx_cntr is 289 | when CLR => nwk_rx_cntr <= (others => '0'); 290 | when INCR => nwk_rx_cntr <= nwk_rx_cntr + 1; 291 | when HOLD => nwk_rx_cntr <= nwk_rx_cntr; 292 | end case; 293 | 294 | -- set the arp_entry_cache 295 | if clear_cache_valid = '1' then 296 | arp_entry_cache <= arp_entry_cache; 297 | cache_valid <= '0'; 298 | elsif store_arp_cache = '1' then 299 | arp_entry_cache <= arp_entry_val; 300 | cache_valid <= '1'; 301 | else 302 | arp_entry_cache <= arp_entry_cache; 303 | cache_valid <= cache_valid; 304 | end if; 305 | 306 | -- freq scaling and 1-sec timer 307 | if freq_scaler = x"00000000" then 308 | freq_scaler <= to_unsigned(CLOCK_FREQ, 32); 309 | else 310 | freq_scaler <= freq_scaler - 1; 311 | end if; 312 | 313 | -- timer processing 314 | case set_timer is 315 | when CLR => 316 | timer <= x"00"; 317 | when INCR => 318 | if timer_enable = '1' then 319 | timer <= timer + 1; 320 | else 321 | timer <= timer; 322 | end if; 323 | when HOLD => 324 | timer <= timer; 325 | end case; 326 | 327 | -- timeout latching 328 | case set_timeout is 329 | when CLR => timeout_reg <= '0'; 330 | when SET => timeout_reg <= '1'; 331 | when HOLD => timeout_reg <= timeout_reg; 332 | end case; 333 | 334 | end if; 335 | end if; 336 | end process; 337 | 338 | end Behavioral; 339 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_TX.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 12:00:04 05/31/2011 6 | -- Design Name: 7 | -- Module Name: arp_tx - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle transmission of an ARP packet. 13 | -- 14 | -- Dependencies: 15 | -- 16 | -- Revision: 17 | -- Revision 0.01 - File Created - refactored this arp_tx module from the complete arp v0.02 module 18 | -- Additional Comments: 19 | -- 20 | ---------------------------------------------------------------------------------- 21 | library IEEE; 22 | use IEEE.STD_LOGIC_1164.all; 23 | use IEEE.NUMERIC_STD.all; 24 | use work.arp_types.all; 25 | 26 | entity arp_tx is 27 | port ( 28 | -- control signals 29 | send_I_have : in std_logic; -- pulse will be latched 30 | arp_entry : in arp_entry_t; -- arp target for I_have req (will be latched) 31 | send_who_has : in std_logic; -- pulse will be latched 32 | ip_entry : in std_logic_vector (31 downto 0); -- IP target for who_has req (will be latched) 33 | -- MAC layer TX signals 34 | mac_tx_req : out std_logic; -- indicates that ip wants access to channel (stays up for as long as tx) 35 | mac_tx_granted : in std_logic; -- indicates that access to channel has been granted 36 | data_out_ready : in std_logic; -- indicates system ready to consume data 37 | data_out_valid : out std_logic; -- indicates data out is valid 38 | data_out_first : out std_logic; -- with data out valid indicates the first byte of a frame 39 | data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame 40 | data_out : out std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 41 | -- system signals 42 | our_mac_address : in std_logic_vector (47 downto 0); 43 | our_ip_address : in std_logic_vector (31 downto 0); 44 | tx_clk : in std_logic; 45 | reset : in std_logic 46 | ); 47 | end arp_tx; 48 | 49 | architecture Behavioral of arp_tx is 50 | 51 | type count_mode_t is (RST, INCR, HOLD); 52 | type set_clr_t is (SET, CLR, HOLD); 53 | type tx_state_t is (IDLE, WAIT_MAC, SEND); 54 | type tx_mode_t is (REPLY, REQUEST); 55 | 56 | -- state variables 57 | signal tx_mac_chn_reqd : std_logic; 58 | signal tx_state : tx_state_t; 59 | signal tx_count : unsigned (7 downto 0); 60 | signal send_I_have_reg : std_logic; 61 | signal send_who_has_reg : std_logic; 62 | signal I_have_target : arp_entry_t; -- latched target for "I have" request 63 | signal who_has_target : std_logic_vector (31 downto 0); -- latched IP for "who has" request 64 | signal tx_mode : tx_mode_t; -- what sort of tx to make 65 | signal target : arp_entry_t; -- target to send to 66 | 67 | -- busses 68 | signal next_tx_state : tx_state_t; 69 | signal tx_mode_val : tx_mode_t; 70 | signal target_val : arp_entry_t; 71 | 72 | -- tx control signals 73 | signal set_tx_state : std_logic; 74 | signal tx_count_mode : count_mode_t; 75 | signal set_chn_reqd : set_clr_t; 76 | signal kill_data_out_valid : std_logic; 77 | signal set_send_I_have : set_clr_t; 78 | signal set_send_who_has : set_clr_t; 79 | signal set_tx_mode : std_logic; 80 | signal set_target : std_logic; 81 | 82 | begin 83 | 84 | tx_combinatorial : process ( 85 | -- input signals 86 | send_I_have, send_who_has, arp_entry, ip_entry, data_out_ready, mac_tx_granted, 87 | our_mac_address, our_ip_address, reset, 88 | -- state variables 89 | tx_state, tx_count, tx_mac_chn_reqd, I_have_target, who_has_target, 90 | send_I_have_reg, send_who_has_reg, tx_mode, target, 91 | -- busses 92 | next_tx_state, tx_mode_val, target_val, 93 | -- control signals 94 | tx_count_mode, kill_data_out_valid, set_send_I_have, set_send_who_has, 95 | set_chn_reqd, set_tx_mode, set_target 96 | ) 97 | begin 98 | -- set output followers 99 | mac_tx_req <= tx_mac_chn_reqd; 100 | 101 | -- set combinatorial output defaults 102 | data_out_first <= '0'; 103 | 104 | case tx_state is 105 | when SEND => 106 | if data_out_ready = '1' and kill_data_out_valid = '0' then 107 | data_out_valid <= '1'; 108 | else 109 | data_out_valid <= '0'; 110 | end if; 111 | when others => data_out_valid <= '0'; 112 | end case; 113 | 114 | -- set bus defaults 115 | next_tx_state <= IDLE; 116 | tx_mode_val <= REPLY; 117 | target_val.ip <= (others => '0'); 118 | target_val.mac <= (others => '1'); 119 | 120 | -- set signal defaults 121 | set_tx_state <= '0'; 122 | tx_count_mode <= HOLD; 123 | data_out <= x"00"; 124 | data_out_last <= '0'; 125 | set_chn_reqd <= HOLD; 126 | kill_data_out_valid <= '0'; 127 | set_send_I_have <= HOLD; 128 | set_send_who_has <= HOLD; 129 | set_tx_mode <= '0'; 130 | set_target <= '0'; 131 | 132 | -- process requests in regardless of FSM state 133 | if send_I_have = '1' then 134 | set_send_I_have <= SET; 135 | end if; 136 | if send_who_has = '1' then 137 | set_send_who_has <= SET; 138 | end if; 139 | 140 | -- TX FSM 141 | case tx_state is 142 | when IDLE => 143 | tx_count_mode <= RST; 144 | if send_I_have_reg = '1' then 145 | set_chn_reqd <= SET; 146 | tx_mode_val <= REPLY; 147 | set_tx_mode <= '1'; 148 | target_val <= I_have_target; 149 | set_target <= '1'; 150 | set_send_I_have <= CLR; 151 | next_tx_state <= WAIT_MAC; 152 | set_tx_state <= '1'; 153 | elsif send_who_has_reg = '1' then 154 | set_chn_reqd <= SET; 155 | tx_mode_val <= REQUEST; 156 | set_tx_mode <= '1'; 157 | target_val.ip <= who_has_target; 158 | target_val.mac <= (others => '1'); 159 | set_target <= '1'; 160 | set_send_who_has <= CLR; 161 | next_tx_state <= WAIT_MAC; 162 | set_tx_state <= '1'; 163 | else 164 | set_chn_reqd <= CLR; 165 | end if; 166 | 167 | when WAIT_MAC => 168 | tx_count_mode <= RST; 169 | if mac_tx_granted = '1' then 170 | next_tx_state <= SEND; 171 | set_tx_state <= '1'; 172 | end if; 173 | -- TODO - should handle timeout here 174 | 175 | when SEND => 176 | if data_out_ready = '1' then 177 | tx_count_mode <= INCR; 178 | end if; 179 | case tx_count is 180 | when x"00" => data_out_first <= data_out_ready; 181 | data_out <= target.mac (47 downto 40); -- target mac--data_out <= x"ff"; -- dst = broadcast 182 | when x"01" => data_out <= target.mac (39 downto 32); --data_out <= x"ff"; 183 | when x"02" => data_out <= target.mac (31 downto 24); --data_out <= x"ff"; 184 | when x"03" => data_out <= target.mac (23 downto 16); --data_out <= x"ff"; 185 | when x"04" => data_out <= target.mac (15 downto 8); --data_out <= x"ff"; 186 | when x"05" => data_out <= target.mac (7 downto 0); --data_out <= x"ff"; 187 | when x"06" => data_out <= our_mac_address (47 downto 40); -- src = our mac 188 | when x"07" => data_out <= our_mac_address (39 downto 32); 189 | when x"08" => data_out <= our_mac_address (31 downto 24); 190 | when x"09" => data_out <= our_mac_address (23 downto 16); 191 | when x"0a" => data_out <= our_mac_address (15 downto 8); 192 | when x"0b" => data_out <= our_mac_address (7 downto 0); 193 | when x"0c" => data_out <= x"08"; -- pkt type = 0806 : ARP 194 | when x"0d" => data_out <= x"06"; 195 | when x"0e" => data_out <= x"00"; -- HW type = 0001 : eth 196 | when x"0f" => data_out <= x"01"; 197 | when x"10" => data_out <= x"08"; -- protocol = 0800 : ip 198 | when x"11" => data_out <= x"00"; 199 | when x"12" => data_out <= x"06"; -- HW size = 06 200 | when x"13" => data_out <= x"04"; -- prot size = 04 201 | 202 | when x"14" => data_out <= x"00"; -- opcode = 203 | when x"15" => 204 | if tx_mode = REPLY then 205 | data_out <= x"02"; -- 02 : REPLY 206 | else 207 | data_out <= x"01"; -- 01 : REQ 208 | end if; 209 | 210 | when x"16" => data_out <= our_mac_address (47 downto 40); -- sender mac 211 | when x"17" => data_out <= our_mac_address (39 downto 32); 212 | when x"18" => data_out <= our_mac_address (31 downto 24); 213 | when x"19" => data_out <= our_mac_address (23 downto 16); 214 | when x"1a" => data_out <= our_mac_address (15 downto 8); 215 | when x"1b" => data_out <= our_mac_address (7 downto 0); 216 | when x"1c" => data_out <= our_ip_address (31 downto 24); -- sender ip 217 | when x"1d" => data_out <= our_ip_address (23 downto 16); 218 | when x"1e" => data_out <= our_ip_address (15 downto 8); 219 | when x"1f" => data_out <= our_ip_address (7 downto 0); 220 | when x"20" => data_out <= target.mac (47 downto 40); -- target mac 221 | when x"21" => data_out <= target.mac (39 downto 32); 222 | when x"22" => data_out <= target.mac (31 downto 24); 223 | when x"23" => data_out <= target.mac (23 downto 16); 224 | when x"24" => data_out <= target.mac (15 downto 8); 225 | when x"25" => data_out <= target.mac (7 downto 0); 226 | when x"26" => data_out <= target.ip (31 downto 24); -- target ip 227 | when x"27" => data_out <= target.ip (23 downto 16); 228 | when x"28" => data_out <= target.ip (15 downto 8); 229 | 230 | when x"29" => 231 | data_out <= target.ip(7 downto 0); 232 | data_out_last <= '1'; 233 | 234 | when x"2a" => 235 | kill_data_out_valid <= '1'; -- data is no longer valid 236 | next_tx_state <= IDLE; 237 | set_tx_state <= '1'; 238 | 239 | when others => 240 | next_tx_state <= IDLE; 241 | set_tx_state <= '1'; 242 | end case; 243 | end case; 244 | end process; 245 | 246 | tx_sequential : process (tx_clk) 247 | begin 248 | if rising_edge(tx_clk) then 249 | if reset = '1' then 250 | -- reset state variables 251 | tx_state <= IDLE; 252 | tx_count <= (others => '0'); 253 | tx_mac_chn_reqd <= '0'; 254 | send_I_have_reg <= '0'; 255 | send_who_has_reg <= '0'; 256 | who_has_target <= (others => '0'); 257 | I_have_target.ip <= (others => '0'); 258 | I_have_target.mac <= (others => '0'); 259 | target.ip <= (others => '0'); 260 | target.mac <= (others => '1'); 261 | 262 | else 263 | -- normal (non reset) processing 264 | 265 | -- Next tx_state processing 266 | if set_tx_state = '1' then 267 | tx_state <= next_tx_state; 268 | else 269 | tx_state <= tx_state; 270 | end if; 271 | 272 | -- input request latching 273 | case set_send_I_have is 274 | when SET => 275 | send_I_have_reg <= '1'; 276 | I_have_target <= arp_entry; 277 | when CLR => 278 | send_I_have_reg <= '0'; 279 | I_have_target <= I_have_target; 280 | when HOLD => 281 | send_I_have_reg <= send_I_have_reg; 282 | I_have_target <= I_have_target; 283 | end case; 284 | 285 | case set_send_who_has is 286 | when SET => 287 | send_who_has_reg <= '1'; 288 | who_has_target <= ip_entry; 289 | when CLR => 290 | send_who_has_reg <= '0'; 291 | who_has_target <= who_has_target; 292 | when HOLD => 293 | send_who_has_reg <= send_who_has_reg; 294 | who_has_target <= who_has_target; 295 | end case; 296 | 297 | -- tx mode 298 | if set_tx_mode = '1' then 299 | tx_mode <= tx_mode_val; 300 | else 301 | tx_mode <= tx_mode; 302 | end if; 303 | 304 | -- target latching 305 | if set_target = '1' then 306 | target <= target_val; 307 | else 308 | target <= target; 309 | end if; 310 | 311 | -- tx_count processing 312 | case tx_count_mode is 313 | when RST => 314 | tx_count <= x"00"; 315 | when INCR => 316 | tx_count <= tx_count + 1; 317 | when HOLD => 318 | tx_count <= tx_count; 319 | end case; 320 | 321 | -- control access request to mac tx chn 322 | case set_chn_reqd is 323 | when SET => tx_mac_chn_reqd <= '1'; 324 | when CLR => tx_mac_chn_reqd <= '0'; 325 | when HOLD => tx_mac_chn_reqd <= tx_mac_chn_reqd; 326 | end case; 327 | 328 | end if; 329 | end if; 330 | end process; 331 | 332 | 333 | end Behavioral; 334 | 335 | -------------------------------------------------------------------------------- /rtl/vhdl/UDP_RX.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 5 June 2011 6 | -- Design Name: 7 | -- Module Name: UDP_RX - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle simple UDP RX 13 | -- doesnt check the checsum 14 | -- Dependencies: 15 | -- 16 | -- Revision: 17 | -- Revision 0.01 - File Created 18 | -- Revision 0.02 - Improved error handling 19 | -- Additional Comments: 20 | -- 21 | ---------------------------------------------------------------------------------- 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.all; 24 | use IEEE.NUMERIC_STD.all; 25 | use work.axi.all; 26 | use work.ipv4_types.all; 27 | 28 | entity UDP_RX is 29 | port ( 30 | -- UDP Layer signals 31 | udp_rx_start : out std_logic; -- indicates receipt of udp header 32 | udp_rxo : out udp_rx_type; 33 | -- system signals 34 | clk : in std_logic; 35 | reset : in std_logic; 36 | -- IP layer RX signals 37 | ip_rx_start : in std_logic; -- indicates receipt of ip header 38 | ip_rx : in ipv4_rx_type 39 | ); 40 | end UDP_RX; 41 | 42 | architecture Behavioral of UDP_RX is 43 | 44 | type rx_state_type is (IDLE, UDP_HDR, USER_DATA, WAIT_END, ERR); 45 | 46 | type rx_event_type is (NO_EVENT, DATA); 47 | type count_mode_type is (RST, INCR, HOLD); 48 | type settable_count_mode_type is (RST, INCR, SET_VAL, HOLD); 49 | type set_clr_type is (SET, CLR, HOLD); 50 | 51 | 52 | -- state variables 53 | signal rx_state : rx_state_type; 54 | signal rx_count : unsigned (15 downto 0); 55 | signal src_port : std_logic_vector (15 downto 0); -- src port captured from input 56 | signal dst_port : std_logic_vector (15 downto 0); -- dst port captured from input 57 | signal data_len : std_logic_vector (15 downto 0); -- user data length captured from input 58 | signal udp_rx_start_reg : std_logic; -- indicates start of user data 59 | signal hdr_valid_reg : std_logic; -- indicates that hdr data is valid 60 | signal src_ip_addr : std_logic_vector (31 downto 0); -- captured from IP hdr 61 | 62 | -- rx control signals 63 | signal next_rx_state : rx_state_type; 64 | signal set_rx_state : std_logic; 65 | signal rx_event : rx_event_type; 66 | signal rx_count_mode : settable_count_mode_type; 67 | signal rx_count_val : unsigned (15 downto 0); 68 | signal set_sph : std_logic; 69 | signal set_spl : std_logic; 70 | signal set_dph : std_logic; 71 | signal set_dpl : std_logic; 72 | signal set_len_H : std_logic; 73 | signal set_len_L : std_logic; 74 | signal set_udp_rx_start : set_clr_type; 75 | signal set_hdr_valid : set_clr_type; 76 | signal dataval : std_logic_vector (7 downto 0); 77 | signal set_pkt_cnt : count_mode_type; 78 | signal set_src_ip : std_logic; 79 | signal set_data_last : std_logic; 80 | 81 | -- IP datagram header format 82 | -- 83 | -- 0 4 8 16 19 24 31 84 | -- -------------------------------------------------------------------------------------------- 85 | -- | source port number | dest port number | 86 | -- | | | 87 | -- -------------------------------------------------------------------------------------------- 88 | -- | length (bytes) | checksum | 89 | -- | (header and data combined) | | 90 | -- -------------------------------------------------------------------------------------------- 91 | -- | Data | 92 | -- | | 93 | -- -------------------------------------------------------------------------------------------- 94 | -- | .... | 95 | -- | | 96 | -- -------------------------------------------------------------------------------------------- 97 | 98 | 99 | begin 100 | 101 | ----------------------------------------------------------------------- 102 | -- combinatorial process to implement FSM and determine control signals 103 | ----------------------------------------------------------------------- 104 | 105 | rx_combinatorial : process ( 106 | -- input signals 107 | ip_rx, ip_rx_start, 108 | -- state variables 109 | rx_state, rx_count, src_port, dst_port, data_len, udp_rx_start_reg, hdr_valid_reg, src_ip_addr, 110 | -- control signals 111 | next_rx_state, set_rx_state, rx_event, rx_count_mode, rx_count_val, 112 | set_sph, set_spl, set_dph, set_dpl, set_len_H, set_len_L, set_data_last, 113 | set_udp_rx_start, set_hdr_valid, dataval, set_pkt_cnt, set_src_ip 114 | ) 115 | begin 116 | -- set output followers 117 | udp_rx_start <= udp_rx_start_reg; 118 | udp_rxo.hdr.is_valid <= hdr_valid_reg; 119 | udp_rxo.hdr.data_length <= data_len; 120 | udp_rxo.hdr.src_port <= src_port; 121 | udp_rxo.hdr.dst_port <= dst_port; 122 | udp_rxo.hdr.src_ip_addr <= src_ip_addr; 123 | 124 | -- transfer data upstream if in user data phase 125 | if rx_state = USER_DATA then 126 | udp_rxo.data.data_in <= ip_rx.data.data_in; 127 | udp_rxo.data.data_in_valid <= ip_rx.data.data_in_valid; 128 | udp_rxo.data.data_in_last <= set_data_last; 129 | else 130 | udp_rxo.data.data_in <= (others => '0'); 131 | udp_rxo.data.data_in_valid <= '0'; 132 | udp_rxo.data.data_in_last <= '0'; 133 | end if; 134 | 135 | -- set signal defaults 136 | next_rx_state <= IDLE; 137 | set_rx_state <= '0'; 138 | rx_event <= NO_EVENT; 139 | rx_count_mode <= HOLD; 140 | set_sph <= '0'; 141 | set_spl <= '0'; 142 | set_dph <= '0'; 143 | set_dpl <= '0'; 144 | set_len_H <= '0'; 145 | set_len_L <= '0'; 146 | set_udp_rx_start <= HOLD; 147 | set_hdr_valid <= HOLD; 148 | dataval <= (others => '0'); 149 | set_src_ip <= '0'; 150 | rx_count_val <= (others => '0'); 151 | set_data_last <= '0'; 152 | 153 | -- determine event (if any) 154 | if ip_rx.data.data_in_valid = '1' then 155 | rx_event <= DATA; 156 | dataval <= ip_rx.data.data_in; 157 | end if; 158 | 159 | -- RX FSM 160 | case rx_state is 161 | when IDLE => 162 | rx_count_mode <= RST; 163 | case rx_event is 164 | when NO_EVENT => -- (nothing to do) 165 | when DATA => 166 | if ip_rx.hdr.protocol = x"11" then 167 | -- UDP protocol 168 | rx_count_mode <= INCR; 169 | set_hdr_valid <= CLR; 170 | set_src_ip <= '1'; 171 | set_sph <= '1'; 172 | next_rx_state <= UDP_HDR; 173 | set_rx_state <= '1'; 174 | else 175 | -- non-UDP protocol - ignore this pkt 176 | set_hdr_valid <= CLR; 177 | next_rx_state <= WAIT_END; 178 | set_rx_state <= '1'; 179 | end if; 180 | end case; 181 | 182 | when UDP_HDR => 183 | case rx_event is 184 | when NO_EVENT => -- (nothing to do) 185 | when DATA => 186 | if rx_count = x"0007" then 187 | rx_count_mode <= SET_VAL; 188 | rx_count_val <= x"0001"; 189 | next_rx_state <= USER_DATA; 190 | set_rx_state <= '1'; 191 | else 192 | rx_count_mode <= INCR; 193 | end if; 194 | -- handle early frame termination 195 | if ip_rx.data.data_in_last = '1' then 196 | next_rx_state <= IDLE; 197 | set_rx_state <= '1'; 198 | else 199 | case rx_count is 200 | when x"0000" => set_sph <= '1'; 201 | when x"0001" => set_spl <= '1'; 202 | when x"0002" => set_dph <= '1'; 203 | when x"0003" => set_dpl <= '1'; 204 | 205 | when x"0004" => set_len_H <= '1'; 206 | when x"0005" => set_len_L <= '1'; set_hdr_valid <= SET; -- header values are now valid, although the pkt may not be for us 207 | 208 | when x"0006" => -- ignore checksum values 209 | when x"0007" => set_udp_rx_start <= SET; -- indicate frame received 210 | 211 | 212 | when others => -- ignore other bytes in udp header 213 | end case; 214 | end if; 215 | end case; 216 | 217 | when USER_DATA => 218 | case rx_event is 219 | when NO_EVENT => -- (nothing to do) 220 | when DATA => 221 | -- note: data gets transfered upstream as part of "output followers" processing 222 | if rx_count = unsigned(data_len) then 223 | set_udp_rx_start <= CLR; 224 | rx_count_mode <= RST; 225 | set_data_last <= '1'; 226 | if ip_rx.data.data_in_last = '1' then 227 | next_rx_state <= IDLE; 228 | set_udp_rx_start <= CLR; 229 | else 230 | next_rx_state <= WAIT_END; 231 | end if; 232 | set_rx_state <= '1'; 233 | else 234 | rx_count_mode <= INCR; 235 | -- check for early frame termination 236 | -- TODO need to mark frame as errored 237 | if ip_rx.data.data_in_last = '1' then 238 | next_rx_state <= IDLE; 239 | set_rx_state <= '1'; 240 | set_data_last <= '1'; 241 | end if; 242 | end if; 243 | end case; 244 | 245 | when ERR => 246 | if ip_rx.data.data_in_last = '0' then 247 | next_rx_state <= WAIT_END; 248 | set_rx_state <= '1'; 249 | else 250 | next_rx_state <= IDLE; 251 | set_rx_state <= '1'; 252 | end if; 253 | 254 | 255 | when WAIT_END => 256 | case rx_event is 257 | when NO_EVENT => -- (nothing to do) 258 | when DATA => 259 | if ip_rx.data.data_in_last = '1' then 260 | next_rx_state <= IDLE; 261 | set_rx_state <= '1'; 262 | end if; 263 | end case; 264 | 265 | end case; 266 | 267 | end process; 268 | 269 | 270 | ----------------------------------------------------------------------------- 271 | -- sequential process to action control signals and change states and outputs 272 | ----------------------------------------------------------------------------- 273 | 274 | rx_sequential : process (clk, reset) 275 | begin 276 | if rising_edge(clk) then 277 | if reset = '1' then 278 | -- reset state variables 279 | rx_state <= IDLE; 280 | rx_count <= x"0000"; 281 | src_port <= (others => '0'); 282 | dst_port <= (others => '0'); 283 | data_len <= (others => '0'); 284 | udp_rx_start_reg <= '0'; 285 | hdr_valid_reg <= '0'; 286 | src_ip_addr <= (others => '0'); 287 | else 288 | -- Next rx_state processing 289 | if set_rx_state = '1' then 290 | rx_state <= next_rx_state; 291 | else 292 | rx_state <= rx_state; 293 | end if; 294 | 295 | -- rx_count processing 296 | case rx_count_mode is 297 | when RST => rx_count <= x"0000"; 298 | when INCR => rx_count <= rx_count + 1; 299 | when SET_VAL => rx_count <= rx_count_val; 300 | when HOLD => rx_count <= rx_count; 301 | end case; 302 | 303 | -- port number capture 304 | if (set_sph = '1') then src_port(15 downto 8) <= dataval; end if; 305 | if (set_spl = '1') then src_port(7 downto 0) <= dataval; end if; 306 | if (set_dph = '1') then dst_port(15 downto 8) <= dataval; end if; 307 | if (set_dpl = '1') then dst_port(7 downto 0) <= dataval; end if; 308 | 309 | if (set_len_H = '1') then 310 | data_len (15 downto 8) <= dataval; 311 | data_len (7 downto 0) <= x"00"; 312 | elsif (set_len_L = '1') then 313 | -- compute data length, taking into account that we need to subtract the header length 314 | data_len <= std_logic_vector(unsigned(data_len(15 downto 8) & dataval) - 8); 315 | else 316 | data_len <= data_len; 317 | end if; 318 | 319 | case set_udp_rx_start is 320 | when SET => udp_rx_start_reg <= '1'; 321 | when CLR => udp_rx_start_reg <= '0'; 322 | when HOLD => udp_rx_start_reg <= udp_rx_start_reg; 323 | end case; 324 | 325 | -- capture src IP address 326 | if set_src_ip = '1' then 327 | src_ip_addr <= ip_rx.hdr.src_ip_addr; 328 | else 329 | src_ip_addr <= src_ip_addr; 330 | end if; 331 | 332 | case set_hdr_valid is 333 | when SET => hdr_valid_reg <= '1'; 334 | when CLR => hdr_valid_reg <= '0'; 335 | when HOLD => hdr_valid_reg <= hdr_valid_reg; 336 | end case; 337 | 338 | end if; 339 | end if; 340 | end process; 341 | 342 | end Behavioral; 343 | 344 | -------------------------------------------------------------------------------- /rtl/vhdl/arpv2.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 12:00:04 05/31/2011 6 | -- Design Name: 7 | -- Module Name: arpv2 - Structural 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle simple IP lookup in 1-deep cache and arp store 13 | -- request cache fill through ARP protocol if required 14 | -- Handle ARP protocol 15 | -- Respond to ARP requests and replies 16 | -- Ignore pkts that are not ARP 17 | -- Ignore pkts that are not addressed to us 18 | -- 19 | -- structural decomposition includes 20 | -- arp TX block - encoding of ARP protocol 21 | -- arp RX block - decoding of ARP protocol 22 | -- arp REQ block - sequencing requests for resolution 23 | -- arp STORE block - storing address resolution entries (indexed by IP addr) 24 | -- arp sync block - sync between master RX clock and TX clock domains 25 | -- 26 | -- Dependencies: 27 | -- 28 | -- Revision: 29 | -- Revision 0.01 - File Created 30 | -- Additional Comments: 31 | -- 32 | ---------------------------------------------------------------------------------- 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.all; 35 | use IEEE.NUMERIC_STD.all; 36 | use work.arp_types.all; 37 | 38 | entity arpv2 is 39 | generic ( 40 | no_default_gateway : boolean := true; -- set to false if communicating with devices accessed 41 | -- though a "default gateway or router" 42 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 43 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 44 | ARP_MAX_PKT_TMO : integer := 5; -- # wrong nwk pkts received before set error 45 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the arp store 46 | ); 47 | port ( 48 | -- lookup request signals 49 | arp_req_req : in arp_req_req_type; 50 | arp_req_rslt : out arp_req_rslt_type; 51 | -- MAC layer RX signals 52 | data_in_clk : in std_logic; 53 | reset : in std_logic; 54 | data_in : in std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 55 | data_in_valid : in std_logic; -- indicates data_in valid on clock 56 | data_in_last : in std_logic; -- indicates last data in frame 57 | -- MAC layer TX signals 58 | mac_tx_req : out std_logic; -- indicates that ip wants access to channel (stays up for as long as tx) 59 | mac_tx_granted : in std_logic; -- indicates that access to channel has been granted 60 | data_out_clk : in std_logic; 61 | data_out_ready : in std_logic; -- indicates system ready to consume data 62 | data_out_valid : out std_logic; -- indicates data out is valid 63 | data_out_first : out std_logic; -- with data out valid indicates the first byte of a frame 64 | data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame 65 | data_out : out std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 66 | -- system signals 67 | our_mac_address : in std_logic_vector (47 downto 0); 68 | our_ip_address : in std_logic_vector (31 downto 0); 69 | nwk_gateway : in std_logic_vector (31 downto 0) := (others => '0'); -- IP address of default gateway 70 | nwk_mask : in std_logic_vector (31 downto 0) := (others => '0'); -- Net mask 71 | control : in arp_control_type; 72 | req_count : out std_logic_vector(7 downto 0) -- count of arp pkts received 73 | ); 74 | end arpv2; 75 | 76 | architecture structural of arpv2 is 77 | 78 | component arp_req 79 | generic ( 80 | no_default_gateway : boolean := true; 81 | CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr 82 | ARP_TIMEOUT : integer := 60; -- ARP response timeout (s) 83 | ARP_MAX_PKT_TMO : integer := 5 -- # wrong nwk pkts received before set error 84 | ); 85 | port ( 86 | -- lookup request signals 87 | arp_req_req : in arp_req_req_type; -- request for a translation from IP to MAC 88 | arp_req_rslt : out arp_req_rslt_type; -- the result 89 | -- external arp store signals 90 | arp_store_req : out arp_store_rdrequest_t; -- requesting a lookup or store 91 | arp_store_result : in arp_store_result_t; -- the result 92 | -- network request signals 93 | arp_nwk_req : out arp_nwk_request_t; -- requesting resolution via the network 94 | arp_nwk_result : in arp_nwk_result_t; -- the result 95 | -- system signals 96 | clear_cache : in std_logic; -- clear the internal cache 97 | nwk_gateway : in std_logic_vector(31 downto 0); -- IP address of default gateway 98 | nwk_mask : in std_logic_vector(31 downto 0); -- Net mask 99 | clk : in std_logic; 100 | reset : in std_logic 101 | ); 102 | end component; 103 | 104 | component arp_tx 105 | port( 106 | -- control signals 107 | send_I_have : in std_logic; -- pulse will be latched 108 | arp_entry : in arp_entry_t; -- arp target for I_have req (will be latched) 109 | send_who_has : in std_logic; -- pulse will be latched 110 | ip_entry : in std_logic_vector (31 downto 0); -- ip target for who_has req (will be latched) 111 | -- MAC layer TX signals 112 | mac_tx_req : out std_logic; -- indicates that ip wants access to channel (stays up for as long as tx) 113 | mac_tx_granted : in std_logic; -- indicates that access to channel has been granted 114 | data_out_ready : in std_logic; -- indicates system ready to consume data 115 | data_out_valid : out std_logic; -- indicates data out is valid 116 | data_out_first : out std_logic; -- with data out valid indicates the first byte of a frame 117 | data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame 118 | data_out : out std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 119 | -- system signals 120 | our_mac_address : in std_logic_vector (47 downto 0); 121 | our_ip_address : in std_logic_vector (31 downto 0); 122 | tx_clk : in std_logic; 123 | reset : in std_logic 124 | ); 125 | end component; 126 | 127 | component arp_rx 128 | port( 129 | -- MAC layer RX signals 130 | data_in : in std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 131 | data_in_valid : in std_logic; -- indicates data_in valid on clock 132 | data_in_last : in std_logic; -- indicates last data in frame 133 | -- ARP output signals 134 | recv_who_has : out std_logic; -- pulse will be latched 135 | arp_entry_for_who_has : out arp_entry_t; -- target for who_has msg (Iie, who to reply to) 136 | recv_I_have : out std_logic; -- pulse will be latched 137 | arp_entry_for_I_have : out arp_entry_t; -- arp target for I_have msg 138 | -- control and status signals 139 | req_count : out std_logic_vector(7 downto 0); -- count of arp pkts received 140 | -- system signals 141 | our_ip_address : in std_logic_vector (31 downto 0); 142 | rx_clk : in std_logic; 143 | reset : in std_logic 144 | ); 145 | end component; 146 | 147 | 148 | component arp_store_br 149 | generic ( 150 | MAX_ARP_ENTRIES : integer := 255 -- max entries in the store 151 | ); 152 | port ( 153 | -- read signals 154 | read_req : in arp_store_rdrequest_t; -- requesting a lookup or store 155 | read_result : out arp_store_result_t; -- the result 156 | -- write signals 157 | write_req : in arp_store_wrrequest_t; -- requesting a lookup or store 158 | -- control and status signals 159 | clear_store : in std_logic; -- erase all entries 160 | entry_count : out unsigned(7 downto 0); -- how many entries currently in store 161 | -- system signals 162 | clk : in std_logic; 163 | reset : in std_logic 164 | ); 165 | end component; 166 | 167 | component arp_sync 168 | port ( 169 | -- REQ to TX 170 | arp_nwk_req : in arp_nwk_request_t; -- request for a translation from IP to MAC 171 | send_who_has : out std_logic; 172 | ip_entry : out std_logic_vector (31 downto 0); 173 | -- RX to TX 174 | recv_who_has : in std_logic; -- this is for us, we will respond 175 | arp_entry_for_who_has : in arp_entry_t; 176 | send_I_have : out std_logic; 177 | arp_entry : out arp_entry_t; 178 | -- RX to REQ 179 | I_have_received : in std_logic; 180 | nwk_result_status : out arp_nwk_rslt_t; 181 | -- System Signals 182 | rx_clk : in std_logic; 183 | tx_clk : in std_logic; 184 | reset : in std_logic 185 | ); 186 | end component; 187 | 188 | 189 | -- interconnect REQ -> ARP_TX 190 | signal arp_nwk_req_int : arp_nwk_request_t; -- tx req from REQ 191 | 192 | signal send_I_have_int : std_logic; 193 | signal arp_entry_int : arp_entry_t; 194 | signal send_who_has_int : std_logic; 195 | signal ip_entry_int : std_logic_vector (31 downto 0); 196 | 197 | -- interconnect REQ <-> ARP_STORE 198 | signal arp_store_req_int : arp_store_rdrequest_t; -- lookup request 199 | signal arp_store_result_int : arp_store_result_t; -- lookup result 200 | 201 | -- interconnect ARP_RX -> REQ 202 | signal nwk_result_status_int : arp_nwk_rslt_t; -- response from a TX req 203 | 204 | -- interconnect ARP_RX -> ARP_STORE 205 | signal recv_I_have_int : std_logic; -- path to store new arp entry 206 | signal arp_entry_for_I_have_int : arp_entry_t; 207 | 208 | -- interconnect ARP_RX -> ARP_TX 209 | signal recv_who_has_int : std_logic; -- path for reply when we can anser 210 | signal arp_entry_for_who_has_int : arp_entry_t; -- target for who_has msg (ie, who to reply to) 211 | 212 | 213 | begin 214 | 215 | 216 | req : arp_req 217 | generic map ( 218 | no_default_gateway => no_default_gateway, 219 | CLOCK_FREQ => CLOCK_FREQ, 220 | ARP_TIMEOUT => ARP_TIMEOUT, 221 | ARP_MAX_PKT_TMO => ARP_MAX_PKT_TMO 222 | ) 223 | port map ( 224 | -- lookup request signals 225 | arp_req_req => arp_req_req, 226 | arp_req_rslt => arp_req_rslt, 227 | -- external arp store signals 228 | arp_store_req => arp_store_req_int, 229 | arp_store_result => arp_store_result_int, 230 | -- network request signals 231 | arp_nwk_req => arp_nwk_req_int, 232 | arp_nwk_result.status => nwk_result_status_int, 233 | arp_nwk_result.entry => arp_entry_for_I_have_int, 234 | -- system signals 235 | clear_cache => control.clear_cache, 236 | nwk_gateway => nwk_gateway, 237 | nwk_mask => nwk_mask, 238 | clk => data_in_clk, 239 | reset => reset 240 | ); 241 | 242 | sync : arp_sync port map ( 243 | -- REQ to TX 244 | arp_nwk_req => arp_nwk_req_int, 245 | send_who_has => send_who_has_int, 246 | ip_entry => ip_entry_int, 247 | -- RX to TX 248 | recv_who_has => recv_who_has_int, 249 | arp_entry_for_who_has => arp_entry_for_who_has_int, 250 | send_I_have => send_I_have_int, 251 | arp_entry => arp_entry_int, 252 | -- RX to REQ 253 | I_have_received => recv_I_have_int, 254 | nwk_result_status => nwk_result_status_int, 255 | -- system 256 | rx_clk => data_in_clk, 257 | tx_clk => data_out_clk, 258 | reset => reset 259 | ); 260 | 261 | tx : arp_tx port map ( 262 | -- control signals 263 | send_I_have => send_I_have_int, 264 | arp_entry => arp_entry_int, 265 | send_who_has => send_who_has_int, 266 | ip_entry => ip_entry_int, 267 | -- MAC layer TX signals 268 | mac_tx_req => mac_tx_req, 269 | mac_tx_granted => mac_tx_granted, 270 | data_out_ready => data_out_ready, 271 | data_out_valid => data_out_valid, 272 | data_out_first => data_out_first, 273 | data_out_last => data_out_last, 274 | data_out => data_out, 275 | -- system signals 276 | our_ip_address => our_ip_address, 277 | our_mac_address => our_mac_address, 278 | tx_clk => data_out_clk, 279 | reset => reset 280 | ); 281 | 282 | rx : arp_rx port map ( 283 | -- MAC layer RX signals 284 | data_in => data_in, 285 | data_in_valid => data_in_valid, 286 | data_in_last => data_in_last, 287 | -- ARP output signals 288 | recv_who_has => recv_who_has_int, 289 | arp_entry_for_who_has => arp_entry_for_who_has_int, 290 | recv_I_have => recv_I_have_int, 291 | arp_entry_for_I_have => arp_entry_for_I_have_int, 292 | -- control and status signals 293 | req_count => req_count, 294 | -- system signals 295 | our_ip_address => our_ip_address, 296 | rx_clk => data_in_clk, 297 | reset => reset 298 | ); 299 | 300 | store : arp_store_br 301 | generic map ( 302 | MAX_ARP_ENTRIES => MAX_ARP_ENTRIES 303 | ) 304 | port map ( 305 | -- read signals 306 | read_req => arp_store_req_int, 307 | read_result => arp_store_result_int, 308 | -- write signals 309 | write_req.req => recv_I_have_int, 310 | write_req.entry => arp_entry_for_I_have_int, 311 | -- control and status signals 312 | clear_store => control.clear_cache, 313 | entry_count => open, 314 | -- system signals 315 | clk => data_in_clk, 316 | reset => reset 317 | ); 318 | 319 | 320 | end structural; 321 | 322 | -------------------------------------------------------------------------------- /bench/vhdl/UDP_RX_tb.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 16:53:03 06/10/2011 6 | -- Design Name: 7 | -- Module Name: C:/Users/pjf/Documents/projects/fpga/xilinx/Network/ip1/UDP_RX_tb.vhd 8 | -- Project Name: ip1 9 | -- Target Device: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- VHDL Test Bench Created by ISE for module: UDP_RX 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created 19 | -- Additional Comments: 20 | -- 21 | -- Notes: 22 | -- This testbench has been automatically generated using types std_logic and 23 | -- std_logic_vector for the ports of the unit under test. Xilinx recommends 24 | -- that these types always be used for the top-level I/O of a design in order 25 | -- to guarantee that the testbench will bind correctly to the post-implementation 26 | -- simulation model. 27 | -------------------------------------------------------------------------------- 28 | library IEEE; 29 | use IEEE.STD_LOGIC_1164.ALL; 30 | use IEEE.NUMERIC_STD.ALL; 31 | use work.axi.all; 32 | use work.ipv4_types.all; 33 | 34 | ENTITY UDP_RX_tb IS 35 | END UDP_RX_tb; 36 | 37 | ARCHITECTURE behavior OF UDP_RX_tb IS 38 | 39 | -- Component Declaration for the Unit Under Test (UUT) 40 | 41 | COMPONENT UDP_RX 42 | PORT( 43 | -- UDP Layer signals 44 | udp_rxo : inout udp_rx_type; 45 | udp_rx_start : out std_logic; -- indicates receipt of udp header 46 | -- system signals 47 | clk : in STD_LOGIC; 48 | reset : in STD_LOGIC; 49 | -- IP layer RX signals 50 | ip_rx_start : in std_logic; -- indicates receipt of ip header 51 | ip_rx : inout ipv4_rx_type 52 | ); 53 | END COMPONENT; 54 | 55 | 56 | --Inputs 57 | signal clk : std_logic := '0'; 58 | signal reset : std_logic := '0'; 59 | signal ip_rx_start : std_logic := '0'; 60 | 61 | --BiDirs 62 | signal udp_rxo : udp_rx_type; 63 | signal ip_rx : ipv4_rx_type; 64 | 65 | --Outputs 66 | signal udp_rx_start : std_logic; 67 | 68 | -- Clock period definitions 69 | constant clk_period : time := 8 ns; 70 | 71 | BEGIN 72 | 73 | -- Instantiate the Unit Under Test (UUT) 74 | uut: UDP_RX PORT MAP ( 75 | udp_rxo => udp_rxo, 76 | udp_rx_start => udp_rx_start, 77 | clk => clk, 78 | reset => reset, 79 | ip_rx_start => ip_rx_start, 80 | ip_rx => ip_rx 81 | ); 82 | 83 | -- Clock process definitions 84 | clk_process :process 85 | begin 86 | clk <= '0'; 87 | wait for clk_period/2; 88 | clk <= '1'; 89 | wait for clk_period/2; 90 | end process; 91 | 92 | 93 | -- Stimulus process 94 | stim_proc: process 95 | begin 96 | -- hold reset state for 100 ns. 97 | wait for 100 ns; 98 | ip_rx_start <= '0'; 99 | ip_rx.data.data_in_valid <= '0'; 100 | ip_rx.data.data_in_last <= '0'; 101 | ip_rx.hdr.is_valid <= '0'; 102 | ip_rx.hdr.protocol <= (others => '0'); 103 | ip_rx.hdr.num_frame_errors <= (others => '0'); 104 | ip_rx.hdr.last_error_code <= (others => '0'); 105 | ip_rx.hdr.is_broadcast <= '0'; 106 | 107 | reset <= '1'; 108 | wait for clk_period*10; 109 | reset <= '0'; 110 | wait for clk_period*5; 111 | reset <= '0'; 112 | 113 | -- check reset conditions 114 | assert udp_rx_start = '0' report "udp_rx_start not initialised correctly on reset"; 115 | assert udp_rxo.hdr.is_valid = '0' report "udp_rxo.hdr.is_valid not initialised correctly on reset"; 116 | assert udp_rxo.data.data_in = x"00" report "udp_rxo.data.data_in not initialised correctly on reset"; 117 | assert udp_rxo.data.data_in_valid = '0' report "udp_rxo.data.data_in_valid not initialised correctly on reset"; 118 | assert udp_rxo.data.data_in_last = '0' report "udp_rxo.data.data_in_last not initialised correctly on reset"; 119 | 120 | -- insert stimulus here 121 | 122 | ------------ 123 | -- TEST 1 -- basic functional rx test with received ip pkt 124 | ------------ 125 | 126 | report "T1: Send an ip frame with IP src ip_address c0a80501, udp protocol from port x1498 to port x8724 and 3 bytes data"; 127 | 128 | ip_rx_start <= '1'; 129 | ip_rx.data.data_in_valid <= '0'; 130 | ip_rx.data.data_in_last <= '0'; 131 | ip_rx.hdr.is_valid <= '1'; 132 | ip_rx.hdr.protocol <= x"11"; -- UDP 133 | ip_rx.hdr.data_length <= x"000b"; 134 | ip_rx.hdr.src_ip_addr<= x"c0a80501"; 135 | wait for clk_period*3; 136 | -- now send the data 137 | ip_rx.data.data_in_valid <= '1'; 138 | ip_rx.data.data_in <= x"14"; wait for clk_period; -- src port 139 | ip_rx.data.data_in <= x"98"; wait for clk_period; 140 | ip_rx.data.data_in <= x"87"; wait for clk_period; -- dst port 141 | ip_rx.data.data_in <= x"24"; wait for clk_period; 142 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- len (hdr + data) 143 | ip_rx.data.data_in <= x"0b"; wait for clk_period; 144 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- mty cks 145 | ip_rx.data.data_in <= x"00"; wait for clk_period; 146 | -- udp hdr should be valid 147 | assert udp_rxo.hdr.is_valid = '1' report "T1: udp_rxo.hdr.is_valid not set"; 148 | 149 | ip_rx.data.data_in <= x"41"; wait for clk_period; -- data 150 | 151 | assert udp_rxo.hdr.src_ip_addr = x"c0a80501" report "T1: udp_rxo.hdr.src_ip_addr not set correctly"; 152 | assert udp_rxo.hdr.src_port = x"1498" report "T1: udp_rxo.hdr.src_port not set correctly"; 153 | assert udp_rxo.hdr.dst_port = x"8724" report "T1: udp_rxo.hdr.dst_port not set correctly"; 154 | assert udp_rxo.hdr.data_length = x"0003" report "T1: udp_rxo.hdr.data_length not set correctly"; 155 | assert udp_rx_start = '1' report "T1: udp_rx_start not set"; 156 | assert udp_rxo.data.data_in_valid = '1' report "T1: udp_rxo.data.data_in_valid not set"; 157 | 158 | ip_rx.data.data_in <= x"45"; wait for clk_period; -- data 159 | ip_rx.data.data_in <= x"49"; ip_rx.data.data_in_last <= '1'; wait for clk_period; 160 | assert udp_rxo.data.data_in_last = '1' report "T1: udp_rxo.data.data_in_last not set"; 161 | ip_rx_start <= '0'; 162 | ip_rx.data.data_in_valid <= '0'; 163 | ip_rx.data.data_in_last <= '0'; 164 | ip_rx.hdr.is_valid <= '0'; 165 | wait for clk_period; 166 | assert udp_rxo.data.data_in = x"00" report "T1: udp_rxo.data.data_in not cleared"; 167 | assert udp_rxo.data.data_in_valid = '0' report "T1: udp_rxo.data.data_in_valid not cleared"; 168 | assert udp_rxo.data.data_in_last = '0' report "T1: udp_rxo.data.data_in_last not cleared"; 169 | 170 | wait for clk_period; 171 | 172 | ------------ 173 | -- TEST 2 -- ability to receive 2nd ip pkt 174 | ------------ 175 | 176 | report "T2: Send an ip frame with IP src ip_address c0a80501, udp protocol from port x7623 to port x0365 and 5 bytes data"; 177 | 178 | ip_rx_start <= '1'; 179 | ip_rx.data.data_in_valid <= '0'; 180 | ip_rx.data.data_in_last <= '0'; 181 | ip_rx.hdr.is_valid <= '1'; 182 | ip_rx.hdr.protocol <= x"11"; -- UDP 183 | ip_rx.hdr.data_length <= x"000b"; 184 | ip_rx.hdr.src_ip_addr<= x"c0a80501"; 185 | wait for clk_period*3; 186 | -- now send the data 187 | ip_rx.data.data_in_valid <= '1'; 188 | ip_rx.data.data_in <= x"76"; wait for clk_period; -- src port 189 | ip_rx.data.data_in <= x"23"; wait for clk_period; 190 | ip_rx.data.data_in <= x"03"; wait for clk_period; -- dst port 191 | ip_rx.data.data_in <= x"65"; wait for clk_period; 192 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- len (hdr + data) 193 | ip_rx.data.data_in <= x"0d"; wait for clk_period; 194 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- mty cks 195 | ip_rx.data.data_in <= x"00"; wait for clk_period; 196 | -- udp hdr should be valid 197 | assert udp_rxo.hdr.is_valid = '1' report "T2: udp_rxo.hdr.is_valid not set"; 198 | 199 | ip_rx.data.data_in <= x"17"; wait for clk_period; -- data 200 | 201 | assert udp_rxo.hdr.src_ip_addr = x"c0a80501" report "T2: udp_rxo.hdr.src_ip_addr not set correctly"; 202 | assert udp_rxo.hdr.src_port = x"7623" report "T2: udp_rxo.hdr.src_port not set correctly"; 203 | assert udp_rxo.hdr.dst_port = x"0365" report "T2: udp_rxo.hdr.dst_port not set correctly"; 204 | assert udp_rxo.hdr.data_length = x"0005" report "T2: udp_rxo.hdr.data_length not set correctly"; 205 | assert udp_rx_start = '1' report "T2: udp_rx_start not set"; 206 | assert udp_rxo.data.data_in_valid = '1' report "T2: udp_rxo.data.data_in_valid not set"; 207 | 208 | ip_rx.data.data_in <= x"37"; wait for clk_period; -- data 209 | ip_rx.data.data_in <= x"57"; wait for clk_period; -- data 210 | ip_rx.data.data_in <= x"73"; wait for clk_period; -- data 211 | ip_rx.data.data_in <= x"f9"; ip_rx.data.data_in_last <= '1'; wait for clk_period; 212 | assert udp_rxo.data.data_in_last = '1' report "T2: udp_rxo.data.data_in_last not set"; 213 | ip_rx_start <= '0'; 214 | ip_rx.data.data_in_valid <= '0'; 215 | ip_rx.data.data_in_last <= '0'; 216 | ip_rx.hdr.is_valid <= '0'; 217 | wait for clk_period; 218 | assert udp_rxo.data.data_in = x"00" report "T2: udp_rxo.data.data_in not cleared"; 219 | assert udp_rxo.data.data_in_valid = '0' report "T2: udp_rxo.data.data_in_valid not cleared"; 220 | assert udp_rxo.data.data_in_last = '0' report "T2: udp_rxo.data.data_in_last not cleared"; 221 | 222 | ------------ 223 | -- TEST 3 -- ability to reject non-udp protocols 224 | ------------ 225 | 226 | report "T3: Send an ip frame with IP src ip_address c0a80501, protocol x12 from port x7623 to port x0365 and 5 bytes data"; 227 | 228 | ip_rx_start <= '1'; 229 | ip_rx.data.data_in_valid <= '0'; 230 | ip_rx.data.data_in_last <= '0'; 231 | ip_rx.hdr.is_valid <= '1'; 232 | ip_rx.hdr.protocol <= x"12"; -- non-UDP 233 | ip_rx.hdr.data_length <= x"000b"; 234 | ip_rx.hdr.src_ip_addr<= x"c0a80501"; 235 | wait for clk_period*3; 236 | -- now send the data 237 | ip_rx.data.data_in_valid <= '1'; 238 | ip_rx.data.data_in <= x"76"; wait for clk_period; -- src port 239 | ip_rx.data.data_in <= x"23"; wait for clk_period; 240 | ip_rx.data.data_in <= x"03"; wait for clk_period; -- dst port 241 | ip_rx.data.data_in <= x"65"; wait for clk_period; 242 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- len (hdr + data) 243 | ip_rx.data.data_in <= x"0d"; wait for clk_period; 244 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- mty cks 245 | ip_rx.data.data_in <= x"00"; wait for clk_period; 246 | -- udp hdr should be valid 247 | assert udp_rxo.hdr.is_valid = '0' report "T3: udp_rxo.hdr.is_valid incorrectly set"; 248 | 249 | ip_rx.data.data_in <= x"17"; wait for clk_period; -- data 250 | 251 | assert udp_rx_start = '0' report "T3: udp_rx_start incorrectly set"; 252 | assert udp_rxo.data.data_in_valid = '0' report "T3: udp_rxo.data.data_in_valid not set"; 253 | 254 | ip_rx.data.data_in <= x"37"; wait for clk_period; -- data 255 | ip_rx.data.data_in <= x"57"; wait for clk_period; -- data 256 | ip_rx.data.data_in <= x"73"; wait for clk_period; -- data 257 | ip_rx.data.data_in <= x"f9"; ip_rx.data.data_in_last <= '1'; wait for clk_period; 258 | assert udp_rxo.data.data_in_last = '0' report "T3: udp_rxo.data.data_in_last incorrectly set"; 259 | ip_rx_start <= '0'; 260 | ip_rx.data.data_in_valid <= '0'; 261 | ip_rx.data.data_in_last <= '0'; 262 | ip_rx.hdr.is_valid <= '0'; 263 | wait for clk_period; 264 | assert udp_rxo.data.data_in = x"00" report "T3: udp_rxo.data.data_in not cleared"; 265 | assert udp_rxo.data.data_in_valid = '0' report "T3: udp_rxo.data.data_in_valid not cleared"; 266 | assert udp_rxo.data.data_in_last = '0' report "T3: udp_rxo.data.data_in_last not cleared"; 267 | 268 | wait for clk_period; 269 | 270 | ------------ 271 | -- TEST 4 -- Ability to receive UDP pkt after non-UDP pkt 272 | ------------ 273 | 274 | report "T4: Send an ip frame with IP src ip_address c0a80501, udp protocol from port x1498 to port x8724 and 3 bytes data"; 275 | 276 | ip_rx_start <= '1'; 277 | ip_rx.data.data_in_valid <= '0'; 278 | ip_rx.data.data_in_last <= '0'; 279 | ip_rx.hdr.is_valid <= '1'; 280 | ip_rx.hdr.protocol <= x"11"; -- UDP 281 | ip_rx.hdr.data_length <= x"000b"; 282 | ip_rx.hdr.src_ip_addr<= x"c0a80501"; 283 | wait for clk_period*3; 284 | -- now send the data 285 | ip_rx.data.data_in_valid <= '1'; 286 | ip_rx.data.data_in <= x"14"; wait for clk_period; -- src port 287 | ip_rx.data.data_in <= x"98"; wait for clk_period; 288 | ip_rx.data.data_in <= x"87"; wait for clk_period; -- dst port 289 | ip_rx.data.data_in <= x"24"; wait for clk_period; 290 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- len (hdr + data) 291 | ip_rx.data.data_in <= x"0b"; wait for clk_period; 292 | ip_rx.data.data_in <= x"00"; wait for clk_period; -- mty cks 293 | ip_rx.data.data_in <= x"00"; wait for clk_period; 294 | -- udp hdr should be valid 295 | assert udp_rxo.hdr.is_valid = '1' report "T4: udp_rxo.hdr.is_valid not set"; 296 | 297 | ip_rx.data.data_in <= x"41"; wait for clk_period; -- data 298 | 299 | assert udp_rxo.hdr.src_ip_addr = x"c0a80501" report "T4: udp_rxo.hdr.src_ip_addr not set correctly"; 300 | assert udp_rxo.hdr.src_port = x"1498" report "T4: udp_rxo.hdr.src_port not set correctly"; 301 | assert udp_rxo.hdr.dst_port = x"8724" report "T4: udp_rxo.hdr.dst_port not set correctly"; 302 | assert udp_rxo.hdr.data_length = x"0003" report "T4: udp_rxo.hdr.data_length not set correctly"; 303 | assert udp_rx_start = '1' report "T4: udp_rx_start not set"; 304 | assert udp_rxo.data.data_in_valid = '1' report "T4: udp_rxo.data.data_in_valid not set"; 305 | 306 | ip_rx.data.data_in <= x"45"; wait for clk_period; -- data 307 | ip_rx.data.data_in <= x"49"; ip_rx.data.data_in_last <= '1'; wait for clk_period; 308 | assert udp_rxo.data.data_in_last = '1' report "T4: udp_rxo.data.data_in_last not set"; 309 | ip_rx_start <= '0'; 310 | ip_rx.data.data_in_valid <= '0'; 311 | ip_rx.data.data_in_last <= '0'; 312 | ip_rx.hdr.is_valid <= '0'; 313 | wait for clk_period; 314 | assert udp_rxo.data.data_in = x"00" report "T4: udp_rxo.data.data_in not cleared"; 315 | assert udp_rxo.data.data_in_valid = '0' report "T4: udp_rxo.data.data_in_valid not cleared"; 316 | assert udp_rxo.data.data_in_last = '0' report "T4: udp_rxo.data.data_in_last not cleared"; 317 | 318 | wait for clk_period; 319 | 320 | report "--- end of tests ---"; 321 | 322 | wait; 323 | end process; 324 | 325 | END; 326 | -------------------------------------------------------------------------------- /rtl/vhdl/arp_RX.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: Peter Fall 4 | -- 5 | -- Create Date: 12:00:04 05/31/2011 6 | -- Design Name: 7 | -- Module Name: arp_rx - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- handle receipt of arp pkt 13 | -- ignores other types of pkt 14 | -- 15 | -- When it receives an ARP pkt that is either addressed to our IP or is a global request, 16 | -- it outputs for a single clock cycle either recv_who_has or recv_I_have along 17 | -- with associated mac or arp entry data. 18 | -- 19 | -- Note that if recv who_has and we have it, then we also assert I_have so that we can cache the rev lookup 20 | -- on the expectation that we will want to reply to this host. 21 | -- 22 | -- Dependencies: 23 | -- 24 | -- Revision: 25 | -- Revision 0.01 - File Created - refactored from arp v0.02 module 26 | -- Additional Comments: 27 | -- 28 | ---------------------------------------------------------------------------------- 29 | library IEEE; 30 | use IEEE.STD_LOGIC_1164.all; 31 | use IEEE.NUMERIC_STD.all; 32 | use work.arp_types.all; 33 | 34 | entity arp_rx is 35 | port ( 36 | -- MAC layer RX signals 37 | data_in : in std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame) 38 | data_in_valid : in std_logic; -- indicates data_in valid on clock 39 | data_in_last : in std_logic; -- indicates last data in frame 40 | -- ARP output signals 41 | recv_who_has : out std_logic; -- pulse will be latched 42 | arp_entry_for_who_has : out arp_entry_t; -- target for who_has msg (Iie, who to reply to) 43 | recv_I_have : out std_logic; -- pulse will be latched 44 | arp_entry_for_I_have : out arp_entry_t; -- arp target for I_have msg 45 | -- control and status signals 46 | req_count : out std_logic_vector(7 downto 0); -- count of arp pkts received 47 | -- system signals 48 | our_ip_address : in std_logic_vector (31 downto 0); 49 | rx_clk : in std_logic; 50 | reset : in std_logic 51 | ); 52 | end arp_rx; 53 | 54 | 55 | architecture Behavioral of arp_rx is 56 | 57 | type rx_state_t is (IDLE, PARSE, PROCESS_ARP, WAIT_END); 58 | type rx_event_t is (NO_EVENT, DATA); 59 | type count_mode_t is (RST, INCR, HOLD); 60 | type arp_oper_t is (NOP, REQUEST, REPLY); 61 | 62 | type tx_state_type is (IDLE, WAIT_MAC, SEND); 63 | 64 | -- state variables 65 | signal send_request_needed : std_logic; 66 | signal tx_mac_chn_reqd : std_logic; 67 | 68 | signal rx_state : rx_state_t; 69 | signal rx_count : unsigned (7 downto 0); 70 | signal arp_operation : arp_oper_t; 71 | signal arp_req_count : unsigned (7 downto 0); 72 | signal new_arp_entry : arp_entry_t; 73 | 74 | -- FIXME - remove these debug state signals 75 | signal arp_err_data : std_logic_vector (7 downto 0); 76 | signal set_err_data : std_logic; 77 | 78 | attribute keep : string; 79 | attribute keep of arp_err_data : signal is "true"; 80 | 81 | 82 | -- rx control signals 83 | signal next_rx_state : rx_state_t; 84 | signal set_rx_state : std_logic; 85 | signal rx_event : rx_event_t; 86 | signal rx_count_mode : count_mode_t; 87 | signal set_arp_oper : std_logic; 88 | signal arp_oper_set_val : arp_oper_t; 89 | signal dataval : std_logic_vector (7 downto 0); 90 | signal count_arp_rcvd : std_logic; 91 | 92 | signal set_mac5 : std_logic; 93 | signal set_mac4 : std_logic; 94 | signal set_mac3 : std_logic; 95 | signal set_mac2 : std_logic; 96 | signal set_mac1 : std_logic; 97 | signal set_mac0 : std_logic; 98 | 99 | signal set_ip3 : std_logic; 100 | signal set_ip2 : std_logic; 101 | signal set_ip1 : std_logic; 102 | signal set_ip0 : std_logic; 103 | 104 | 105 | 106 | -- function to determine whether the rx pkt is an arp pkt and whether we want to process it 107 | -- Returns 1 if we should discard 108 | -- The following will make us ignore the frame (all values hexadecimal): 109 | -- PDU type /= 0806 110 | -- Protocol Type /= 0800 111 | -- Hardware Type /= 1 112 | -- Hardware Length /= 6 113 | -- Protocol Length /= 4 114 | -- Operation /= 1 or 2 115 | -- Target IP /= our IP (i.er. message is not meant for us) 116 | -- 117 | function not_our_arp(data : std_logic_vector; count : unsigned; our_ip : std_logic_vector) return std_logic is 118 | begin 119 | if 120 | (count = 12 and data /= x"08") or -- PDU type 0806 : ARP 121 | (count = 13 and data /= x"06") or 122 | (count = 14 and data /= x"00") or -- HW type 1 : eth 123 | (count = 15 and data /= x"01") or 124 | (count = 16 and data /= x"08") or -- Protocol 0800 : IP 125 | (count = 17 and data /= x"00") or 126 | (count = 18 and data /= x"06") or -- HW Length 6 127 | (count = 19 and data /= x"04") or -- protocol length 4 128 | (count = 20 and data /= x"00") or -- operation 1 or 2 (req or reply) 129 | (count = 21 and data /= x"01" and data /= x"02") or 130 | (count = 38 and data /= our_ip(31 downto 24)) or -- target IP is ours 131 | (count = 39 and data /= our_ip(23 downto 16)) or 132 | (count = 40 and data /= our_ip(15 downto 8)) or 133 | (count = 41 and data /= our_ip(7 downto 0)) 134 | then 135 | return '1'; 136 | else 137 | return '0'; 138 | end if; 139 | end function not_our_arp; 140 | 141 | begin 142 | 143 | rx_combinatorial : process ( 144 | -- input signals 145 | data_in, data_in_valid, data_in_last, our_ip_address, 146 | -- state variables 147 | rx_state, rx_count, arp_operation, arp_req_count, arp_err_data, new_arp_entry, 148 | -- control signals 149 | next_rx_state, set_rx_state, rx_event, rx_count_mode, set_arp_oper, arp_oper_set_val, 150 | dataval, set_mac5, set_mac4, set_mac3, set_mac2, set_mac1, set_mac0, set_ip3, set_ip2, set_ip1, set_ip0, set_err_data, 151 | count_arp_rcvd 152 | ) 153 | begin 154 | -- set output followers 155 | req_count <= std_logic_vector(arp_req_count); 156 | 157 | -- set defaults for combinatorial outputs 158 | recv_who_has <= '0'; 159 | arp_entry_for_who_has.ip <= (others => '0'); 160 | arp_entry_for_who_has.mac <= (others => '0'); 161 | recv_I_have <= '0'; 162 | arp_entry_for_I_have.ip <= (others => '0'); 163 | arp_entry_for_I_have.mac <= (others => '0'); 164 | 165 | -- set signal defaults 166 | next_rx_state <= IDLE; 167 | set_rx_state <= '0'; 168 | rx_event <= NO_EVENT; 169 | rx_count_mode <= HOLD; 170 | set_arp_oper <= '0'; 171 | arp_oper_set_val <= NOP; 172 | dataval <= (others => '0'); 173 | set_mac5 <= '0'; 174 | set_mac4 <= '0'; 175 | set_mac3 <= '0'; 176 | set_mac2 <= '0'; 177 | set_mac1 <= '0'; 178 | set_mac0 <= '0'; 179 | set_ip3 <= '0'; 180 | set_ip2 <= '0'; 181 | set_ip1 <= '0'; 182 | set_ip0 <= '0'; 183 | count_arp_rcvd <= '0'; 184 | set_err_data <= '0'; 185 | 186 | -- determine event (if any) 187 | if data_in_valid = '1' then 188 | rx_event <= DATA; 189 | end if; 190 | 191 | -- RX FSM 192 | case rx_state is 193 | when IDLE => 194 | rx_count_mode <= RST; 195 | case rx_event is 196 | when NO_EVENT => -- (nothing to do) 197 | when DATA => 198 | next_rx_state <= PARSE; 199 | set_rx_state <= '1'; 200 | rx_count_mode <= INCR; 201 | end case; 202 | 203 | when PARSE => 204 | case rx_event is 205 | when NO_EVENT => -- (nothing to do) 206 | when DATA => 207 | rx_count_mode <= INCR; 208 | -- handle early frame termination 209 | if data_in_last = '1' then 210 | next_rx_state <= IDLE; 211 | rx_count_mode <= RST; 212 | set_rx_state <= '1'; 213 | --else 214 | end if; 215 | -- check for end of frame. Also, detect and discard if not our frame 216 | if not_our_arp(data_in, rx_count, our_ip_address) = '1' then 217 | dataval <= data_in; 218 | set_err_data <= '1'; 219 | next_rx_state <= WAIT_END; 220 | set_rx_state <= '1'; 221 | 222 | else 223 | case (to_integer(rx_count)) is 224 | when 41 => 225 | next_rx_state <= PROCESS_ARP; 226 | set_rx_state <= '1'; 227 | when 21 => -- capture ARP operation 228 | case (data_in) is 229 | when x"01" => 230 | arp_oper_set_val <= REQUEST; 231 | set_arp_oper <= '1'; 232 | when x"02" => 233 | arp_oper_set_val <= REPLY; 234 | set_arp_oper <= '1'; 235 | when others => -- ignore other values 236 | end case; 237 | -- capture source mac addr 238 | when 22 => 239 | set_mac5 <= '1'; 240 | dataval <= data_in; 241 | when 23 => 242 | set_mac4 <= '1'; 243 | dataval <= data_in; 244 | when 24 => 245 | set_mac3 <= '1'; 246 | dataval <= data_in; 247 | when 25 => 248 | set_mac2 <= '1'; 249 | dataval <= data_in; 250 | when 26 => 251 | set_mac1 <= '1'; 252 | dataval <= data_in; 253 | when 27 => 254 | set_mac0 <= '1'; 255 | dataval <= data_in; 256 | when 28 => -- capture source ip addr 257 | set_ip3 <= '1'; 258 | dataval <= data_in; 259 | when 29 => 260 | set_ip2 <= '1'; 261 | dataval <= data_in; 262 | when 30 => 263 | set_ip1 <= '1'; 264 | dataval <= data_in; 265 | when 31 => 266 | set_ip0 <= '1'; 267 | dataval <= data_in; 268 | when others => -- do nothing 269 | end case; 270 | end if; 271 | -- end if; 272 | end case; 273 | 274 | when PROCESS_ARP => 275 | next_rx_state <= WAIT_END; 276 | set_rx_state <= '1'; 277 | arp_oper_set_val <= NOP; 278 | set_arp_oper <= '1'; 279 | case arp_operation is 280 | when NOP => -- (nothing to do) 281 | when REQUEST => 282 | count_arp_rcvd <= '1'; 283 | recv_who_has <= '1'; 284 | arp_entry_for_who_has <= new_arp_entry; 285 | -- setting I_Have as well allows us to cache the remote node's entry immediately 286 | recv_I_have <= '1'; 287 | arp_entry_for_I_have <= new_arp_entry; 288 | when REPLY => 289 | count_arp_rcvd <= '1'; 290 | recv_I_have <= '1'; 291 | arp_entry_for_I_have <= new_arp_entry; 292 | end case; 293 | 294 | when WAIT_END => 295 | case rx_event is 296 | when NO_EVENT => -- (nothing to do) 297 | when DATA => 298 | if data_in_last = '1' then 299 | next_rx_state <= IDLE; 300 | rx_count_mode <= RST; 301 | set_rx_state <= '1'; 302 | end if; 303 | end case; 304 | 305 | end case; 306 | 307 | end process; 308 | 309 | rx_sequential : process (rx_clk) 310 | begin 311 | if rising_edge(rx_clk) then 312 | if reset = '1' then 313 | -- reset state variables 314 | rx_state <= IDLE; 315 | rx_count <= x"00"; 316 | arp_operation <= NOP; 317 | arp_req_count <= x"00"; 318 | arp_err_data <= (others => '0'); 319 | else 320 | -- Next rx_state processing 321 | if set_rx_state = '1' then 322 | rx_state <= next_rx_state; 323 | else 324 | rx_state <= rx_state; 325 | end if; 326 | 327 | -- rx_count processing 328 | case rx_count_mode is 329 | when RST => 330 | rx_count <= x"00"; 331 | when INCR => 332 | rx_count <= rx_count + 1; 333 | when HOLD => 334 | rx_count <= rx_count; 335 | end case; 336 | 337 | -- err data 338 | if set_err_data = '1' then 339 | arp_err_data <= data_in; 340 | else 341 | arp_err_data <= arp_err_data; 342 | end if; 343 | 344 | -- arp operation processing 345 | if set_arp_oper = '1' then 346 | arp_operation <= arp_oper_set_val; 347 | else 348 | arp_operation <= arp_operation; 349 | end if; 350 | 351 | -- source mac capture 352 | if (set_mac5 = '1') then new_arp_entry.mac(47 downto 40) <= dataval; end if; 353 | if (set_mac4 = '1') then new_arp_entry.mac(39 downto 32) <= dataval; end if; 354 | if (set_mac3 = '1') then new_arp_entry.mac(31 downto 24) <= dataval; end if; 355 | if (set_mac2 = '1') then new_arp_entry.mac(23 downto 16) <= dataval; end if; 356 | if (set_mac1 = '1') then new_arp_entry.mac(15 downto 8) <= dataval; end if; 357 | if (set_mac0 = '1') then new_arp_entry.mac(7 downto 0) <= dataval; end if; 358 | 359 | -- source ip capture 360 | if (set_ip3 = '1') then new_arp_entry.ip(31 downto 24) <= dataval; end if; 361 | if (set_ip2 = '1') then new_arp_entry.ip(23 downto 16) <= dataval; end if; 362 | if (set_ip1 = '1') then new_arp_entry.ip(15 downto 8) <= dataval; end if; 363 | if (set_ip0 = '1') then new_arp_entry.ip(7 downto 0) <= dataval; end if; 364 | 365 | -- set arp entry request 366 | if count_arp_rcvd = '1' then 367 | -- count another ARP pkt received 368 | arp_req_count <= arp_req_count + 1; 369 | else 370 | arp_req_count <= arp_req_count; 371 | end if; 372 | 373 | end if; 374 | end if; 375 | end process; 376 | 377 | end Behavioral; 378 | 379 | -------------------------------------------------------------------------------- /bench/vhdl/arp_STORE_tb.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 07:38:43 02/13/2012 6 | -- Design Name: 7 | -- Module Name: arp_STORE_tb.vhd 8 | -- Project Name: udp3 9 | -- Target Device: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- VHDL Test Bench Created by ISE for module: arp_STORE_br 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created 19 | -- Additional Comments: 20 | -- 21 | -- Notes: 22 | -- This testbench has been automatically generated using types std_logic and 23 | -- std_logic_vector for the ports of the unit under test. Xilinx recommends 24 | -- that these types always be used for the top-level I/O of a design in order 25 | -- to guarantee that the testbench will bind correctly to the post-implementation 26 | -- simulation model. 27 | -------------------------------------------------------------------------------- 28 | library IEEE; 29 | use IEEE.STD_LOGIC_1164.ALL; 30 | use IEEE.NUMERIC_STD.ALL; 31 | use ieee.std_logic_unsigned.all; 32 | use work.arp_types.all; 33 | 34 | ENTITY arp_STORE_tb IS 35 | END arp_STORE_tb; 36 | 37 | ARCHITECTURE behavior OF arp_STORE_tb IS 38 | 39 | -- Component Declaration for the Unit Under Test (UUT) 40 | 41 | COMPONENT arp_STORE_br 42 | generic ( 43 | MAX_ARP_ENTRIES : integer := 256 -- max entries in the store 44 | ); 45 | PORT( 46 | -- read signals 47 | read_req : in arp_store_rdrequest_t; -- requesting a '1' or store 48 | read_result : out arp_store_result_t; -- the result 49 | -- write signals 50 | write_req : in arp_store_wrrequest_t; -- requesting a '1' or store 51 | -- control and status signals 52 | clear_store : in std_logic; -- erase all entries 53 | entry_count : out unsigned(7 downto 0); -- how many entries currently in store 54 | -- system signals 55 | clk : in std_logic; 56 | reset : in STD_LOGIC 57 | ); 58 | END COMPONENT; 59 | 60 | 61 | --Inputs 62 | signal read_req : arp_store_rdrequest_t; 63 | signal write_req : arp_store_wrrequest_t; 64 | signal clear_store : std_logic := '0'; 65 | signal clk : std_logic := '0'; 66 | signal reset : std_logic := '0'; 67 | 68 | --Outputs 69 | signal read_result : arp_store_result_t; 70 | signal entry_count : unsigned(7 downto 0); -- how many entries currently in store 71 | 72 | -- Clock period definitions 73 | constant clk_period : time := 8 ns; 74 | 75 | BEGIN 76 | 77 | -- Instantiate the Unit Under Test (UUT) 78 | uut: arp_STORE_br 79 | generic map ( 80 | MAX_ARP_ENTRIES => 4 81 | ) 82 | PORT MAP ( 83 | read_req => read_req, 84 | read_result => read_result, 85 | write_req => write_req, 86 | clear_store => clear_store, 87 | entry_count => entry_count, 88 | clk => clk, 89 | reset => reset 90 | ); 91 | 92 | -- Clock process definitions 93 | clk_process :process 94 | begin 95 | clk <= '0'; 96 | wait for clk_period/2; 97 | clk <= '1'; 98 | wait for clk_period/2; 99 | end process; 100 | 101 | 102 | -- Stimulus process 103 | stim_proc: process 104 | begin 105 | read_req.req <= '0'; 106 | read_req.ip <= (others => '0'); 107 | write_req.req <= '0'; 108 | write_req.entry.ip <= (others => '0'); 109 | write_req.entry.mac <= (others => '0'); 110 | reset <= '1'; 111 | -- hold reset state 112 | wait for clk_period*10; 113 | reset <= '0'; 114 | 115 | -- insert stimulus here 116 | report "T1 - look for something when store is empty"; 117 | read_req.ip <= x"12345678"; 118 | read_req.req <= '1'; 119 | wait for clk_period*4; 120 | assert read_result.status = NOT_FOUND report "T1: expected NOT_FOUND"; 121 | wait for clk_period; 122 | read_req.req <= '0'; 123 | wait for clk_period*2; 124 | assert read_result.status = IDLE report "T1: expected IDLE"; 125 | assert entry_count = x"00" report "T1: wrong entry count"; 126 | 127 | report "T2 - insert first entry into store"; 128 | write_req.entry.ip <= x"12345678"; 129 | write_req.entry.mac <= x"002398127645"; 130 | write_req.req <= '1'; 131 | wait for clk_period; 132 | write_req.req <= '0'; 133 | wait until read_result.status = IDLE; 134 | wait for clk_period; 135 | assert entry_count = x"01" report "T2: wrong entry count"; 136 | 137 | report "T3 - check if can find this single entry"; 138 | read_req.ip <= x"12345678"; 139 | read_req.req <= '1'; 140 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 141 | wait for clk_period; 142 | assert read_result.status = FOUND report "T3: expected FOUND"; 143 | assert read_result.entry.ip = x"12345678" report "T3: wrong ip addr"; 144 | assert read_result.entry.mac = x"002398127645" report "T3: wrong mac addr"; 145 | wait for clk_period; 146 | read_req.req <= '0'; 147 | wait for clk_period*3; 148 | assert read_result.status = IDLE report "T3: expected IDLE"; 149 | 150 | report "T4 - check unable to find missing entry with one entry in store"; 151 | read_req.ip <= x"12345679"; 152 | read_req.req <= '1'; 153 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 154 | wait for clk_period; 155 | assert read_result.status = NOT_FOUND report "T4: expected NOT_FOUND"; 156 | wait for clk_period; 157 | read_req.req <= '0'; 158 | wait for clk_period*3; 159 | assert read_result.status = IDLE report "T4: expected IDLE"; 160 | 161 | report "T5 - insert 2nd entry into store and check can find both entries"; 162 | write_req.entry.ip <= x"12345679"; 163 | write_req.entry.mac <= x"101202303404"; 164 | write_req.req <= '1'; 165 | wait for clk_period; 166 | write_req.req <= '0'; 167 | wait until read_result.status = IDLE; 168 | wait for clk_period; 169 | assert entry_count = x"02" report "T4: wrong entry count"; 170 | read_req.ip <= x"12345678"; 171 | read_req.req <= '1'; 172 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 173 | wait for clk_period; 174 | assert read_result.status = FOUND report "T5.1: expected FOUND"; 175 | assert read_result.entry.ip = x"12345678" report "T5.1: wrong ip addr"; 176 | assert read_result.entry.mac = x"002398127645" report "T5.1: wrong mac addr"; 177 | read_req.req <= '0'; 178 | wait for clk_period*3; 179 | assert read_result.status = IDLE report "T5.1: expected IDLE"; 180 | read_req.ip <= x"12345679"; 181 | read_req.req <= '1'; 182 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 183 | wait for clk_period; 184 | assert read_result.status = FOUND report "T5.2: expected FOUND"; 185 | assert read_result.entry.ip = x"12345679" report "T5.2: wrong ip addr"; 186 | assert read_result.entry.mac = x"101202303404" report "T5.2: wrong mac addr"; 187 | read_req.req <= '0'; 188 | wait for clk_period*3; 189 | assert read_result.status = IDLE report "T5.2: expected IDLE"; 190 | 191 | report "T6 - insert 2 more entries so that the store is full. check can find all"; 192 | write_req.entry.ip <= x"1234567a"; 193 | write_req.entry.mac <= x"10120230340a"; 194 | write_req.req <= '1'; 195 | wait for clk_period; 196 | write_req.req <= '0'; 197 | wait until read_result.status = IDLE; 198 | wait for clk_period; 199 | write_req.entry.ip <= x"1234567b"; 200 | write_req.entry.mac <= x"10120230340b"; 201 | write_req.req <= '1'; 202 | wait for clk_period; 203 | write_req.req <= '0'; 204 | wait until read_result.status = IDLE; 205 | wait for clk_period; 206 | assert entry_count = x"04" report "T6: wrong entry count"; 207 | read_req.ip <= x"12345678"; 208 | read_req.req <= '1'; 209 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 210 | wait for clk_period; 211 | assert read_result.status = FOUND report "T6.1: expected FOUND"; 212 | assert read_result.entry.ip = x"12345678" report "T6.1: wrong ip addr"; 213 | assert read_result.entry.mac = x"002398127645" report "T6.1: wrong mac addr"; 214 | read_req.req <= '0'; 215 | wait for clk_period*3; 216 | assert read_result.status = IDLE report "T6.1: expected IDLE"; 217 | read_req.ip <= x"12345679"; 218 | read_req.req <= '1'; 219 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 220 | wait for clk_period; 221 | assert read_result.status = FOUND report "T6.2: expected FOUND"; 222 | assert read_result.entry.ip = x"12345679" report "T6.2: wrong ip addr"; 223 | assert read_result.entry.mac = x"101202303404" report "T6.2: wrong mac addr"; 224 | read_req.req <= '0'; 225 | wait for clk_period*3; 226 | assert read_result.status = IDLE report "T6.2: expected IDLE"; 227 | read_req.ip <= x"1234567a"; 228 | read_req.req <= '1'; 229 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 230 | wait for clk_period; 231 | assert read_result.status = FOUND report "T6.3: expected FOUND"; 232 | assert read_result.entry.ip = x"1234567a" report "T6.3: wrong ip addr"; 233 | assert read_result.entry.mac = x"10120230340a" report "T6.3: wrong mac addr"; 234 | read_req.req <= '0'; 235 | wait for clk_period*3; 236 | assert read_result.status = IDLE report "T6.3: expected IDLE"; 237 | read_req.ip <= x"1234567b"; 238 | read_req.req <= '1'; 239 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 240 | wait for clk_period; 241 | assert read_result.status = FOUND report "T6.4: expected FOUND"; 242 | assert read_result.entry.ip = x"1234567b" report "T6.4: wrong ip addr"; 243 | assert read_result.entry.mac = x"10120230340b" report "T6.4: wrong mac addr"; 244 | read_req.req <= '0'; 245 | wait for clk_period*3; 246 | assert read_result.status = IDLE report "T6.4: expected IDLE"; 247 | 248 | report "T7 - with store full, check that we dont find missing item"; 249 | read_req.ip <= x"1233367b"; 250 | read_req.req <= '1'; 251 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 252 | wait for clk_period; 253 | assert read_result.status = NOT_FOUND report "T7: expected NOT_FOUND"; 254 | read_req.req <= '0'; 255 | wait for clk_period*3; 256 | assert read_result.status = IDLE report "T7: expected IDLE"; 257 | 258 | report "T8 - insert additional entry into store - will erase one of the others"; 259 | write_req.entry.ip <= x"12345699"; 260 | write_req.entry.mac <= x"992398127699"; 261 | write_req.req <= '1'; 262 | wait for clk_period; 263 | write_req.req <= '0'; 264 | wait until read_result.status = IDLE; 265 | wait for clk_period; 266 | assert entry_count = x"04" report "T8: wrong entry count"; 267 | read_req.ip <= x"12345699"; 268 | read_req.req <= '1'; 269 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 270 | wait for clk_period; 271 | assert read_result.status = FOUND report "T8: expected FOUND"; 272 | assert read_result.entry.ip = x"12345699" report "T8: wrong ip addr"; 273 | assert read_result.entry.mac = x"992398127699" report "T8: wrong mac addr"; 274 | read_req.req <= '0'; 275 | wait for clk_period*3; 276 | assert read_result.status = IDLE report "T8: expected IDLE"; 277 | 278 | report "T9 - clear the store and ensure cant find something that was there"; 279 | clear_store <= '1'; 280 | wait for clk_period; 281 | clear_store <= '0'; 282 | wait for clk_period; 283 | assert entry_count = x"00" report "T9: wrong entry count"; 284 | read_req.ip <= x"12345699"; 285 | read_req.req <= '1'; 286 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 287 | wait for clk_period; 288 | assert read_result.status = NOT_FOUND report "T9: expected NOT_FOUND"; 289 | read_req.req <= '0'; 290 | wait for clk_period*3; 291 | assert read_result.status = IDLE report "T9: expected IDLE"; 292 | 293 | report "T10 - refill the store with three entries"; 294 | write_req.entry.ip <= x"12345675"; 295 | write_req.entry.mac <= x"10120230340a"; 296 | write_req.req <= '1'; 297 | wait for clk_period; 298 | write_req.req <= '0'; 299 | wait until read_result.status = IDLE; 300 | wait for clk_period; 301 | write_req.entry.ip <= x"12345676"; 302 | write_req.entry.mac <= x"10120230340b"; 303 | write_req.req <= '1'; 304 | wait for clk_period; 305 | write_req.req <= '0'; 306 | wait until read_result.status = IDLE; 307 | wait for clk_period; 308 | write_req.entry.ip <= x"12345677"; 309 | write_req.entry.mac <= x"10120230340c"; 310 | write_req.req <= '1'; 311 | wait for clk_period; 312 | write_req.req <= '0'; 313 | wait until read_result.status = IDLE; 314 | wait for clk_period; 315 | assert entry_count = x"03" report "T10: wrong entry count"; 316 | 317 | report "T11 - check middle entry, then change it and check again"; 318 | read_req.ip <= x"12345676"; 319 | read_req.req <= '1'; 320 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 321 | wait for clk_period; 322 | assert read_result.status = FOUND report "T11.1: expected FOUND"; 323 | assert read_result.entry.ip = x"12345676" report "T11.1: wrong ip addr"; 324 | assert read_result.entry.mac = x"10120230340b" report "T11.1: wrong mac addr"; 325 | read_req.req <= '0'; 326 | wait for clk_period*3; 327 | assert read_result.status = IDLE report "T11.1: expected IDLE"; 328 | write_req.entry.ip <= x"12345676"; 329 | write_req.entry.mac <= x"10120990340b"; 330 | write_req.req <= '1'; 331 | wait for clk_period; 332 | write_req.req <= '0'; 333 | wait for clk_period; 334 | assert entry_count = x"03" report "T11: wrong entry count"; 335 | read_req.ip <= x"12345676"; 336 | read_req.req <= '1'; 337 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 338 | wait for clk_period; 339 | assert read_result.status = FOUND report "T11.2: expected FOUND"; 340 | assert read_result.entry.ip = x"12345676" report "T11.2: wrong ip addr"; 341 | assert read_result.entry.mac = x"10120990340b" report "T11.2: wrong mac addr"; 342 | read_req.req <= '0'; 343 | wait for clk_period*3; 344 | assert read_result.status = IDLE report "T11.2: expected IDLE"; 345 | 346 | report "T12 - check 2nd write at beginning"; 347 | -- clear store, write 1st entry, overwrite the entry, and check 348 | clear_store <= '1'; 349 | wait for clk_period; 350 | clear_store <= '0'; 351 | wait for clk_period; 352 | assert entry_count = x"00" report "T12.1: wrong entry count"; 353 | write_req.entry.ip <= x"12345678"; 354 | write_req.entry.mac <= x"002398127645"; 355 | write_req.req <= '1'; 356 | wait for clk_period; 357 | write_req.req <= '0'; 358 | wait until read_result.status = IDLE; 359 | wait for clk_period; 360 | assert entry_count = x"01" report "T12.2: wrong entry count"; 361 | write_req.entry.ip <= x"12345678"; 362 | write_req.entry.mac <= x"002398127647"; 363 | write_req.req <= '1'; 364 | wait for clk_period; 365 | write_req.req <= '0'; 366 | wait until read_result.status = IDLE; 367 | wait for clk_period; 368 | assert entry_count = x"01" report "T12.3: wrong entry count"; 369 | read_req.ip <= x"12345678"; 370 | read_req.req <= '1'; 371 | wait until read_result.status = FOUND or read_result.status = NOT_FOUND; 372 | wait for clk_period; 373 | assert read_result.status = FOUND report "T12.4: expected FOUND"; 374 | assert read_result.entry.ip = x"12345678" report "T12.4: wrong ip addr"; 375 | assert read_result.entry.mac = x"002398127647" report "T12.4: wrong mac addr"; 376 | read_req.req <= '0'; 377 | wait for clk_period*3; 378 | assert read_result.status = IDLE report "T12.5: expected IDLE"; 379 | 380 | report "--- end of tests ---"; 381 | wait; 382 | end process; 383 | 384 | END; 385 | --------------------------------------------------------------------------------