diff options
Diffstat (limited to 'src/ipv4_rx_c.v')
| -rw-r--r-- | src/ipv4_rx_c.v | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/ipv4_rx_c.v b/src/ipv4_rx_c.v new file mode 100644 index 0000000..262d328 --- /dev/null +++ b/src/ipv4_rx_c.v @@ -0,0 +1,134 @@ +/* + * ipv4_rx_c.v + * + * Copyright (C) 2024-2025 Private Island Networks Inc. + * 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 for the internal controller + * + * + * 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.................................... + * + * + */ + +module ipv4_rx_c #(parameter IP_DST_MATCH_1=192, IP_DST_MATCH_2=168, + IP_DST_MATCH_3=5, IP_DST_MATCH_4=200) +( + input rstn, + input clk, + + // control + input phy_up, + + // packet data + input pkt_start, // assert for each new frame to start state machines + input rx_sample, // enable in case we have connected at 100 Mbit + 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 ip_addr_match +); + + /* 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; + + /* + * rx_state machine + * capture an IPv4 Packet + * + */ + always @(posedge clk, negedge rstn) + if (!rstn) + rx_state <= RX_ST_IDLE; + else if ( rx_eop || !phy_up ) // EOP will reset state machine + rx_state <= RX_ST_IDLE; + else + 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; + default: rx_state <= RX_ST_IDLE; + endcase + + /* 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_sample && rx_state != RX_ST_IDLE && rx_sample) || 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 }; + + // IPv4 Dest Address match logic + always @(posedge clk, negedge rstn) + if (!rstn) + ip_addr_match <= 1'b0; + else if (rx_eop) + ip_addr_match <= 1'b0; + else if ( rx_sample && rx_data_m1 == (IP_DST_MATCH_4) && rx_data_m2 == IP_DST_MATCH_3 && rx_data_m3 == IP_DST_MATCH_2 && rx_data_m4 == IP_DST_MATCH_1 ) + ip_addr_match <= 1'b1; + + assign pkt_complete = ( rx_state >= RX_ST_DATA && rx_pkt_length == rx_byte_cnt+1 ) ? 1'b1 : 1'b0; + + +endmodule |



