diff options
Diffstat (limited to 'src/ipv4_tx_c.v')
| -rw-r--r-- | src/ipv4_tx_c.v | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/ipv4_tx_c.v b/src/ipv4_tx_c.v new file mode 100644 index 0000000..3c33548 --- /dev/null +++ b/src/ipv4_tx_c.v @@ -0,0 +1,179 @@ +/* + * ipv4_tx.v + * + * Copyright 2025 Private Island Networks Inc. + * Copyright 2018, 2019, 2020 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: Layer 3 (and 4) Support for Controller Transmit + * + * + */ + +module ipv4_tx_c( + input rstn, + input phy_resetn, + input clk, + + // Control Interface + input cont_clk, // controller clock + input cont_sel, + input cont_we, + input [7:0] cont_addr, + input [15:0] cont_d_i, + output reg [15:0] cont_d_o, + + // Line State + input mode_100Mbit, + input phy_up, + + // Switch I/F + input [2:0] tx_mode, + input [2:0] tx_src_sel, + input [10:0] byte_cnt_i, + + // MAC Interface + input fifo_re_i, + output reg fifo_empty_o, + output reg [8:0] fifo_d_o, + + // Debug + output [7:0] gpio +); + +`define INCLUDED +`include "ethernet_params.v" +`include "rgmii_params.v" +`undef INCLUDED + + localparam TX_CNT_OFFSET = 11'h15; // offset for start of IP Header in Ethernet frame + localparam TX_CNT_CKSUM_START = TX_CNT_OFFSET + 10; + + wire ipv4_hdr_active; + reg [10:0] tx_cnt; + reg [17:0] ipv4_cksum; + reg [15:0] ipv4_pkt_length; + reg [15:0] udp_pkt_length; + integer i; + + assign ipv4_hdr_active = (tx_mode == TX_MODE_XMT_CUSTOM && tx_src_sel == TX_SRC_SEL_UC); + + always @(posedge clk, negedge rstn) + if ( !rstn ) + tx_cnt <= 11'd0; + else if (ipv4_hdr_active) + tx_cnt <= tx_cnt + 1'b1; + else + tx_cnt <= 11'd0; + + + always @(posedge clk, negedge rstn) + if ( !rstn ) begin + ipv4_pkt_length <= 16'd0; + udp_pkt_length <= 16'd0; + end + else if (ipv4_hdr_active && tx_cnt == 11'd0) begin + ipv4_pkt_length <= byte_cnt_i + SZ_IPV4_HEADER + SZ_UDP_HEADER; + udp_pkt_length <= byte_cnt_i + SZ_UDP_HEADER; + end + + always @(posedge clk, negedge rstn) + if ( !rstn ) + ipv4_cksum <= 18'd0; + else if (!ipv4_hdr_active) + ipv4_cksum <= 18'd0; + else if (tx_cnt < 11'd20 && tx_cnt[0]) + ipv4_cksum <= ipv4_cksum + (ipv4_hdr(tx_cnt-1)<<8) + ipv4_hdr(tx_cnt); + // else if (tx_cnt == 11'd20) + // ipv4_cksum <= ipv4_cksum + ipv4_pkt_length; + else if (tx_cnt == 11'd21) + ipv4_cksum <= {2'b00,ipv4_cksum[15:0]} + {16'h0000,ipv4_cksum[17:16]}; + else if (tx_cnt == 11'd22) + ipv4_cksum <= {2'b00, ~ipv4_cksum[15:0]}; + + // fifo_empty_o + always @(posedge clk, negedge rstn) + if ( !rstn ) + fifo_empty_o <= 1'b1; + else if (tx_cnt >= TX_CNT_OFFSET && tx_cnt < (TX_CNT_OFFSET + SZ_IPV4_HEADER + SZ_UDP_HEADER)) + fifo_empty_o <= 1'b0; + else + fifo_empty_o <= 1'b1; + + // fifo_d_o + always @(posedge clk, negedge rstn) + if ( !rstn ) + fifo_d_o <= 9'h000; + else if (tx_cnt == TX_CNT_CKSUM_START) + fifo_d_o <= ipv4_cksum[15:8]; + else if (tx_cnt == TX_CNT_CKSUM_START+1) + fifo_d_o <= ipv4_cksum[7:0]; + else if (tx_cnt >= TX_CNT_OFFSET && tx_cnt < TX_CNT_OFFSET + SZ_IPV4_HEADER) + fifo_d_o <= ipv4_hdr(tx_cnt-TX_CNT_OFFSET); + else if (tx_cnt >= TX_CNT_OFFSET && tx_cnt < TX_CNT_OFFSET + SZ_IPV4_HEADER + SZ_UDP_HEADER) + fifo_d_o <= udp_hdr(tx_cnt-(TX_CNT_OFFSET + SZ_IPV4_HEADER)); + else + fifo_d_o <= 9'h000; + + + // generate the IPv4 header + // Assuming the header is only 20 bytes, this is both efficient and flexible + function automatic [7:0] ipv4_hdr; + input [10:0] ad; + case(ad) + 0: ipv4_hdr = 8'h45; // Version + 1: ipv4_hdr = 8'h00; // IHL + 2: ipv4_hdr = ipv4_pkt_length[15:8]; // Total Length + 3: ipv4_hdr = ipv4_pkt_length[7:0]; + 4: ipv4_hdr = 8'h54; + 5: ipv4_hdr = 8'hDB; + 6: ipv4_hdr = 8'h40; + 7: ipv4_hdr = 8'h00; + 8: ipv4_hdr = 8'h40; // TTL + 9: ipv4_hdr = 8'h11; // L4 Protocol (UDP=0x11) + 10: ipv4_hdr = 8'h00; // Checksum + 11: ipv4_hdr = 8'h00; + 12: ipv4_hdr = 8'd192; // IP Source Address + 13: ipv4_hdr = 8'd168; + 14: ipv4_hdr = 8'd5; + 15: ipv4_hdr = 8'd100; + 16: ipv4_hdr = 8'd192; // IP Destination Address + 17: ipv4_hdr = 8'd168; + 18: ipv4_hdr = 8'd5; + 19: ipv4_hdr = 8'd40; + default: ipv4_hdr = 8'h00; + endcase + endfunction + + + // generate the UDP header + function automatic [7:0] udp_hdr; + input [10:0] ad; + case(ad) + 0: udp_hdr = 8'h80; // SRC Port + 1: udp_hdr = 8'h00; // + 2: udp_hdr = 8'h80; // DST Port + 3: udp_hdr = 8'h00; + 4: udp_hdr = udp_pkt_length[15:8]; // Length + 5: udp_hdr = udp_pkt_length[7:0]; + 6: udp_hdr = 8'h00; //Checksum + 7: udp_hdr = 8'h00; + default: udp_hdr = 8'h00; + endcase + endfunction + + assign gpio[0] = |ipv4_cksum[7:0]; + assign gpio[1] = |ipv4_cksum[15:8]; + +endmodule |



