summaryrefslogtreecommitdiffhomepage
path: root/src/ipv4_tx_c.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipv4_tx_c.v')
-rw-r--r--src/ipv4_tx_c.v179
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

Highly Recommended Verilog Books