summaryrefslogtreecommitdiffhomepage
path: root/source/ipv4.v
diff options
context:
space:
mode:
Diffstat (limited to 'source/ipv4.v')
-rw-r--r--source/ipv4.v152
1 files changed, 152 insertions, 0 deletions
diff --git a/source/ipv4.v b/source/ipv4.v
new file mode 100644
index 0000000..55ab7a7
--- /dev/null
+++ b/source/ipv4.v
@@ -0,0 +1,152 @@
+/*
+ * ipv4.v
+ *
+ * Copyright (C) 2018, 2019 Mind Chasers Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * function: Receive State Machine and Logic for IPv4
+ *
+ *
+ * 0-7 8-15 16-23 24-31
+ * 0 Version/IHL TOS Total Length.............
+ * 4 Identification...... Flags/Frag Off...........
+ * 8 TTL Protocol Header Checksum..........
+ * 12 Source IP Address....................................
+ * 16 Dest IP Address......................................
+ * 20 Options / Padding....................................
+ *
+ *
+ * When pkt_start is detected, rx_data_m2 has the first byte
+ */
+
+`timescale 1ns /10ps
+
+module ipv4_rx (
+ input rstn,
+ input clk,
+
+ // control
+ input phy_resetn,
+ input phy_up,
+
+ // packet data
+ input pkt_start, // assert for each new frame to start state machines
+ input rx_eop, // use as a synch reset
+ input[7:0] rx_data_m1,
+ input[7:0] rx_data_m2,
+ input[7:0] rx_data_m3, // first byte of packet appears here simultaneous with pkt_start
+ input[7:0] rx_data_m4,
+
+ // flags
+ output pkt_complete,
+ output reg trigger_src_addr,
+ output reg trigger_dst_addr,
+ output reg keep
+ );
+
+ /* Byte Address (when last byte of field is present on rx_data_m1 ) */
+ localparam IPV4_TOS=1, IPV4_LENGTH=3, IPV4_IP_ID=5, IPV4_PROTOCOL=9,
+ IPV4_HDR_CKSUM=11, IPV4_SRC_ADDR=15, IPV4_DST_ADDR=19;
+
+ localparam RX_ST_IDLE=4'h0, RX_ST_DATA=4'h1, RX_ST_DONE=4'h2, RX_ST_3=4'h3,
+ RX_ST_4=4'h4, RX_ST_5=4'h5, RX_ST_6=4'h6, RX_ST_7=4'h7,
+ RX_ST_8=4'h8, RX_ST_9=4'h9, RX_ST_A=4'ha, RX_ST_B=4'hb,
+ RX_ST_C=4'hc, RX_ST_D=4'hd, RX_ST_E=4'he, RX_ST_F=4'hf;
+
+ localparam IPV4_PROTO_ICMP = 1, IPV4_PROTO_IGMP = 2, IPV4_PROTO_TCP = 6, IPV4_PROTO_UDP = 17,
+ IPV4_PROTO_ENCAP = 41, IPV4_PROTO_OSPF = 89, IPV4_PROTO_SCTP = 132;
+
+
+ reg [3:0] rx_state;
+ reg [10:0] rx_byte_cnt;
+ reg [10:0] rx_pkt_length;
+ reg [7:0] protocol;
+ wire rx_error;
+
+ /*
+ * rx_state machine
+ * capture an IPv4 Packet
+ *
+ */
+ always @(posedge clk, negedge rstn)
+ if (!rstn)
+ rx_state <= RX_ST_IDLE;
+ else if ( rx_eop || !phy_resetn ) // EOP will reset state machine
+ rx_state <= RX_ST_IDLE;
+ else if ( phy_up )
+ case ( rx_state )
+ RX_ST_IDLE: if ( pkt_start ) // Found /S/
+ rx_state <= RX_ST_DATA;
+ RX_ST_DATA: if (pkt_complete)
+ rx_state <= RX_ST_DONE;
+ RX_ST_DONE: rx_state <= RX_ST_IDLE;
+ endcase
+ else
+ rx_state <= RX_ST_IDLE;
+
+
+ /* rx_byte_cnt */
+ always @(posedge clk, negedge rstn)
+ if (!rstn)
+ rx_byte_cnt <= 0;
+ else if ( rx_state == RX_ST_IDLE && !pkt_start ) // synch reset
+ rx_byte_cnt <= 1;
+ else if ( rx_state != RX_ST_IDLE || pkt_start )
+ rx_byte_cnt <= rx_byte_cnt + 1;
+
+
+ /* protocol */
+ always @(posedge clk, negedge rstn)
+ if ( !rstn )
+ protocol <= 0;
+ else if ( rx_eop )
+ protocol <= 0;
+ else if ( rx_byte_cnt == IPV4_PROTOCOL )
+ protocol <= rx_data_m1;
+
+
+ /* rx_pkt_length */
+ always @(posedge clk, negedge rstn)
+ if ( !rstn )
+ rx_pkt_length <= 11'h7ff;
+ else if ( rx_eop )
+ rx_pkt_length <= 11'h7ff;
+ else if ( rx_state == RX_ST_DATA && rx_byte_cnt == IPV4_LENGTH )
+ rx_pkt_length <= { rx_data_m2[2:0], rx_data_m1 };
+
+ /*
+ * Packet Filter Trigger(s), assert the sample before the data appears
+ *
+ */
+ always @(posedge clk, negedge rstn)
+ if (!rstn)
+ trigger_src_addr <= 1'b0;
+ else if ( rx_byte_cnt == IPV4_SRC_ADDR-1 )
+ trigger_src_addr <= 1'b1;
+ else
+ trigger_src_addr <= 1'b0;
+
+ always @(posedge clk, negedge rstn)
+ if (!rstn)
+ trigger_dst_addr <= 1'b0;
+ else if ( rx_byte_cnt == IPV4_DST_ADDR-1 )
+ trigger_dst_addr <= 1'b1;
+ else
+ trigger_dst_addr <= 1'b0;
+
+ assign pkt_complete = ( rx_state >= RX_ST_DATA && rx_pkt_length == rx_byte_cnt+1 ) ? 1 : 0;
+ assign rx_error = 0;
+
+
+endmodule