summaryrefslogtreecommitdiffhomepage
path: root/source/ipv4.v
blob: 55ab7a797ad8aee3d3af9d725600f26edbc65ea6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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