summaryrefslogtreecommitdiffhomepage
path: root/source/mac.v
diff options
context:
space:
mode:
Diffstat (limited to 'source/mac.v')
-rw-r--r--source/mac.v380
1 files changed, 229 insertions, 151 deletions
diff --git a/source/mac.v b/source/mac.v
index 8941710..b5b980a 100644
--- a/source/mac.v
+++ b/source/mac.v
@@ -1,7 +1,7 @@
/*
* mac.v
*
- * Copyright (C) 2018, 2019 Mind Chasers Inc.
+ * Copyright 2018, 2019, 2020, 2021 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.
@@ -15,38 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * function: SGMII TX/RX/AN state machines
+ * function: Ethernet MAC Layer
*
*/
-`timescale 1ns /10ps
-
module mac(
input rstn,
input phy_resetn, // The external PHY has its reset signal asserted
input clk,
input tap_port,
- // SGMII AN
- input link_timer,
+ // PCS / SERDES health
+ input rx_lsm,
+ input rx_cv_err,
+ input rx_disp_err,
+ input rx_cdr_lol,
+ input rx_los,
+
+ // AN
+ input [1:0] phy_type, // SGMII==0, SX=1, SMA=3
+ input pulse_1_6ms, // SGMII
+ input pulse_10ms, // SX
input [1:0] fixed_speed,
input an_disable,
- output reg an_link_up,
- output reg an_duplex,
- output reg phy_up,
+ output an_duplex,
+ output phy_up,
output reg mode_100Mbit,
// Switch I/F
- input [1:0] tx_mode,
+ input [2:0] tx_mode,
output reg tx_f,
- // PCS / SERDES health
- input rx_lsm,
- input rx_cv_err,
- input rx_disp_err,
- input rx_cdr_lol,
- input rx_los,
-
// PCS data I/F
input rx_k,
input [7:0] rx_data,
@@ -54,11 +53,6 @@ module mac(
output reg [7:0] tx_data,
output reg tx_disp_correct,
- // Flags and Interrupts
- output reg rx_enet_bcast,
- output reg rx_ipv4_arp,
- output keep,
-
// TX FCS
output reg fcs_init,
output reg fcs_enable,
@@ -66,13 +60,18 @@ module mac(
output reg [7:0] fcs_dout,
input [7:0] fcs_din,
- // SGMII RX / FIFO Write
+ // MAC RX / FIFO Write
output rx_fifo_we,
output [8:0] rx_fifo_d,
output reg rx_error,
+ output rx_keep,
output reg rx_wr_done,
+ output reg [10:0] rx_byte_cnt,
+ output [1:0] rx_mode,
- // SGMII TX / FIFO Read
+ // MAC TX / FIFO Read
+ input [10:0] tx_byte_cnt_i,
+ input [2:0] tx_src_sel,
output reg tx_fifo_re,
input [8:0] tx_fifo_d,
input tx_fifo_empty,
@@ -82,7 +81,6 @@ module mac(
output reg ipv4_pkt_start,
output reg trigger,
-
output reg rx_k_m1,
output reg rx_k_m2,
output reg rx_k_m3,
@@ -93,14 +91,16 @@ module mac(
output reg[7:0] rx_data_m3,
output reg[7:0] rx_data_m4,
- // Param RAM for TAP port
+ // Param RAM
output [10:0] dpr_ad,
output dpr_we,
output dpr_ce,
input [8:0] dpr_di,
output [8:0] dpr_do,
- // Metrics and Interrupts
+ // Flags, Metrics, Interrupts, and Debug
+ output reg rx_enet_bcast,
+ output reg rx_ipv4_arp,
output reg mac_int,
output reg rx_sop, // start of packet
output reg rx_eop,
@@ -108,19 +108,22 @@ module mac(
output reg tx_eop,
output reg metrics_start,
input [8:0] metrics_d,
-
- // Debug
output reg rx_active,
output reg tx_active
);
`include "sgmii_params.v"
`include "ethernet_params.v"
-
+
+localparam PHY_TYPE_SGMII = 2'b00,
+ PHY_TYPE_SX = 2'b01,
+ PHY_TYPE_RSVD = 2'b10,
+ PHY_TYPE_SMA = 2'b11;
+
localparam AN_TX_CONFIG_HI = 8'h00,
AN_TX_CONFIG_HI_ACK = 8'h40,
- AN_TX_CONFIG_LO = 8'h01;
-
+ AN_TX_CONFIG_LO = 8'h21;
+
localparam RX_ST_IDLE=4'h0, RX_ST_SOP=4'h1, RX_ST_PREAMBLE=4'h2, RX_ST_SFD=4'h3, RX_ST_MAC_ADDR=4'h4,
RX_ST_MAC_TYPE0=4'h5, RX_ST_MAC_TYPE1=4'h6, RX_ST_DATA=4'h7, RX_ST_DATA_DONE0=4'h8,
RX_ST_DATA_DONE1=4'h9, RX_ST_DATA_DONE2=4'ha;
@@ -130,27 +133,30 @@ localparam TX_ST_0=4'h0, TX_ST_1=4'h1, TX_ST_2=4'h2, TX_ST_3=4'h3,
TX_ST_8=4'h8, TX_ST_9=4'h9, TX_ST_A=4'ha, TX_ST_B=4'hb,
TX_ST_C=4'hc, TX_ST_D=4'hd, TX_ST_E=4'he, TX_ST_F=4'hf;
-reg [3:0] rx_cnt_100mbit, tx_cnt_100mbit;
+// AN
+wire [15:0] tx_config_reg;
+wire [1:0] an_speed;
+reg [3:0] rx_cnt_100mbit, tx_cnt_100mbit;
wire tx_sample, tx_sample_re;
wire rx_packet_complete;
wire mode_1Gbit;
-reg [1:0] an_speed;
reg [3:0] rx_state;
-reg [10:0] rx_byte_cnt;
reg [10:0] rx_pkt_length;
reg [15:0] rx_l3_proto;
+// TODO: consider reorganizing state machines to reuse registers.
reg [7:0] tx_data_an, tx_data_idle, tx_data_pkt;
reg tx_k_an, tx_k_idle, tx_k_pkt;
// Transmit Registers and Wires
reg [3:0] tx_state; // transmit state machine
reg [10:0] tx_byte_cnt;
-reg [5:0] param_addr;
+reg [10:0] param_addr;
reg tx_f_an, tx_f_idle, tx_f_pkt;
+reg i_tx_disp_correct;
reg tx_last_byte;
// FIFOs:
@@ -165,6 +171,16 @@ reg [8:0] dpr_di_reg;
// counter for detecting Ethernet broadcast, only needs to count to 6
reg [2:0] rx_enet_bcast_cnt;
+// layer 3 TX support
+reg [18:0] tx_ipv4_cksum;
+reg [15:0] tx_ipv4_length;
+
+// layer 4 TX support
+reg [15:0] tx_udp_length;
+
+wire tx_finished;
+wire tx_temp;
+
/*
* RX DIRECTION
@@ -200,47 +216,34 @@ always @(posedge clk or negedge rstn)
end
end
-/*
- * SGMII Auto Negotiation State Machine
- * Look for configuration /C/ ordered set
- * /C/ is Alternating /C1/ and /C2/
- * /C1/: /K28.5/D21.5/Config_Reg
- * /C2/: /K28.5/D2.2/Config_Reg
- * Config Reg: Low High
- *
- * Not using a link timer and not counting 3 frames because testing rmshows it's unnecessary
- *
- */
-always @(posedge clk or negedge rstn)
- if (!rstn)
- begin
- an_link_up <= 1'b0;
- an_duplex <= 1'b0;
- an_speed <= SGMII_SPEED_RSVD;
- phy_up <= 1'b0;
- end
- else if ( !phy_resetn )
- begin
- an_link_up <= 1'b0;
- an_duplex <= 1'b0;
- an_speed <= SGMII_SPEED_RSVD;
- phy_up <= 1'b0;
- end
- else if ( an_disable )
- begin
- phy_up <= 1'b1;
- end
- // D21.5 is part of config ( M2 has low, M1 has high )
- else if (!rx_k_m1 && !rx_k_m2 && !rx_k_m3 && rx_data_m3 == D21_5 && rx_k_m4 && rx_data_m4 == K28_5 )
- begin
- an_link_up <= rx_data_m1[7];
- an_duplex <= rx_data_m1[4];
- an_speed <= rx_data_m1[3:2];
- phy_up <= 1'b0;
- end
- // IDLE2 1:0xBC, 0:0x50
- else if ( !rx_k_m1 && rx_data_m1 == D16_2 && rx_k_m2 == 1'b1 && rx_data_m2 == K28_5 )
- phy_up <= 1'b1;
+// Auto Negotiation
+an an_inst (
+ .rstn(rstn),
+ .phy_resetn(phy_resetn),
+ .clk(clk),
+ // AN
+ .phy_type(phy_type),
+ .pulse_1_6ms(pulse_1_6ms),
+ .pulse_10ms(pulse_10ms),
+ .fixed_speed(fixed_speed),
+ .an_disable(an_disable),
+ .an_duplex(an_duplex),
+ .an_speed(an_speed),
+ .an_link_up(an_link_up),
+ .tx_config_reg(tx_config_reg),
+ .phy_up(phy_up),
+
+ .rx_k_m1(rx_k_m1),
+ .rx_k_m2(rx_k_m2),
+ .rx_k_m3(rx_k_m3),
+ .rx_k_m4(rx_k_m4),
+
+ .rx_data_m1(rx_data_m1),
+ .rx_data_m2(rx_data_m2),
+ .rx_data_m3(rx_data_m3),
+ .rx_data_m4(rx_data_m4)
+ );
+
// 100 MBit Support. There are no plans to support 10 MBit, so 100 MBit inactive is the same as 1GBit active
// if/else encodes the priority
@@ -270,7 +273,8 @@ always @(posedge clk or negedge rstn)
/*
* rx_state machine
* capture the Ethernet MAC header + packet.
-*/
+ *
+ */
always @(posedge clk, negedge rstn)
if (!rstn)
rx_state <= RX_ST_IDLE;
@@ -310,9 +314,13 @@ always @(posedge clk, negedge rstn)
*/
assign rx_fifo_we = ( rx_sample && ( rx_state >= RX_ST_SFD && rx_state <= RX_ST_DATA_DONE1 ) ) ? 1'b1 : 1'b0;
+// rx_mode
+assign rx_mode = 2'b00;
+
/*
* Detect Ethernet Broadcast (destination address = ff:ff:ff:ff:ff:ff)
+ * TODO: Add state information to only trigger on DEST ADDRESS
*
*/
always @(posedge clk, negedge rstn)
@@ -369,14 +377,14 @@ always @(posedge clk, negedge rstn)
rx_ipv4_arp <= 1'b0;
/*
- * keep flag
+ * rx_keep flag
* signals must be one shot
*
*/
- assign keep = rx_enet_bcast | rx_ipv4_arp;
-
+ assign rx_keep = rx_enet_bcast | rx_ipv4_arp;
/* rx_error
+ * TODO: should be one shot?
* */
always @(*)
if ( rx_sample && rx_state >= RX_ST_DATA && ( rx_l3_proto != ETHER_TYPE_IPV4 && rx_l3_proto != ETHER_TYPE_IPV6 && rx_l3_proto != ETHER_TYPE_ARP) )
@@ -478,9 +486,10 @@ always @(posedge clk or negedge rstn)
*/
- // TX 100 Mbit support
-assign tx_sample_re = (tx_cnt_100mbit == 4'd8 && mode_100Mbit) || !mode_100Mbit ? 1'b1 : 1'b0;
-assign tx_sample = (tx_cnt_100mbit == 4'd9 && mode_100Mbit) || !mode_100Mbit ? 1'b1 : 1'b0;
+// TX 100 Mbit support
+assign tx_sample_re = (tx_cnt_100mbit == 4'd8 && mode_100Mbit) || !mode_100Mbit;
+assign tx_sample = (tx_cnt_100mbit == 4'd9 && mode_100Mbit) || !mode_100Mbit;
+
always @(posedge clk or negedge rstn)
if (!rstn)
tx_cnt_100mbit <= 4'b0;
@@ -496,41 +505,42 @@ always @(posedge clk or negedge rstn)
*
* Transmit Mux
*/
-always@(*)
- begin
+always @(posedge clk or negedge rstn)
+ if (!rstn) begin
+ tx_data <= 8'h00;
+ tx_k <= 1'b0;
+ tx_disp_correct <= 1'b0;
+ end
+ else begin
case(tx_mode)
- TX_MODE_AN :
- begin
- tx_data = tx_data_an;
- tx_k = tx_k_an;
- tx_f = tx_f_an;
- end
- TX_MODE_IDLE :
- begin
- tx_data = tx_data_idle;
- tx_k = tx_k_idle;
- tx_f = tx_f_idle;
- end
- TX_MODE_XMT_PKT :
+ TX_MODE_AN:
begin
- tx_data = tx_data_pkt;
- tx_k = tx_k_pkt;
- tx_f = tx_f_pkt;
+ tx_data <= tx_data_an;
+ tx_k <= tx_k_an;
+ tx_disp_correct <= i_tx_disp_correct;
end
- TX_MODE_XMT_METRICS :
+ TX_MODE_IDLE:
begin
- tx_data = tx_data_pkt;
- tx_k = tx_k_pkt;
- tx_f = tx_f_pkt;
+ tx_data <= tx_data_idle;
+ tx_k <= tx_k_idle;
+ tx_disp_correct <= i_tx_disp_correct;
end
- default :
+ default:
begin
- tx_data = K_ERROR;
- tx_k = 1'b1;
- tx_f = 1'b1;
+ tx_data <= tx_data_pkt;
+ tx_k <= tx_k_pkt;
+ tx_disp_correct <= i_tx_disp_correct;
end
endcase
end
+
+// tx_f mux
+always @(*)
+ case(tx_mode)
+ TX_MODE_AN: tx_f <= tx_f_an;
+ TX_MODE_IDLE: tx_f <= tx_f_idle;
+ default : tx_f <= tx_f_pkt;
+ endcase
/*
@@ -544,46 +554,46 @@ always @(*)
tx_f_an = 1'b0;
tx_k_an = 1'b0;
case(tx_byte_cnt[2:0])
- 3'd0:
- begin
- tx_data_an = K28_5;
- tx_k_an = 1'b1;
- end
- 3'd1:
+ 3'd0:
+ begin
+ tx_data_an = K28_5;
+ tx_k_an = 1'b1;
+ end
+ 3'd1:
tx_data_an = D21_5;
- 3'd2:
+ 3'd2:
tx_data_an = AN_TX_CONFIG_LO;
- 3'd3:
+ 3'd3:
if (!an_link_up)
tx_data_an = AN_TX_CONFIG_HI;
- else
+ else
tx_data_an = AN_TX_CONFIG_HI_ACK;
- 3'd4:
- begin
- tx_data_an = K28_5;
- tx_k_an = 1'b1;
- end
- 3'd5:
+ 3'd4:
+ begin
+ tx_data_an = K28_5;
+ tx_k_an = 1'b1;
+ end
+ 3'd5:
tx_data_an = D2_2;
- 3'd6:
+ 3'd6:
tx_data_an = AN_TX_CONFIG_LO;
- 3'd7:
+ 3'd7:
if (!an_link_up)
begin
- tx_f_an = 1'b1;
+ tx_f_an = 1'b1;
tx_data_an = AN_TX_CONFIG_HI;
end
else
begin
- tx_f_an = 1'b1;
+ tx_f_an = 1'b1;
tx_data_an = AN_TX_CONFIG_HI_ACK;
end
default:
- begin
- tx_data_an = K_ERROR;
- tx_k_an = 1'b1;
- tx_f_an = 1'b1;
- end
+ begin
+ tx_data_an = K_ERROR;
+ tx_k_an = 1'b1;
+ tx_f_an = 1'b1;
+ end
endcase
end
@@ -613,16 +623,23 @@ always @(*)
end
+/*
+ * TX Finished Logic
+ */
+assign tx_temp = (tx_mode==TX_MODE_XMT_CUSTOM && tx_byte_cnt==tx_ipv4_length+SZ_ETH_HEADER);
+assign tx_finished = tx_last_byte || (tx_mode==TX_MODE_XMT_CUSTOM && tx_byte_cnt==(tx_ipv4_length+SZ_ETH_HEADER));
+
+
/*
-* Transmit Packet State Machine for TX_MODE_XMT_PKT and TX_MODE_XMT_METRICS
+* Transmit Packet State Machine
*
*
* Note: the first /I/ following a transmitted frame or Configuration ordered set
* restores the current positive or negative running disparity to a
-* negative value.
-*
+* negative value.
+*
*/
always @(posedge clk, negedge rstn)
begin
@@ -640,9 +657,9 @@ always @(posedge clk, negedge rstn)
tx_state <= TX_ST_3; // preamble 0x55, assert tx_fifo_re, reset tx_byte_cnt
TX_ST_3: if ( tx_sample )
tx_state <= TX_ST_4; // preamble 0xD5
- TX_ST_4: if ( tx_sample && tx_last_byte && tx_byte_cnt < 60 ) // check if we need to pad?
+ TX_ST_4: if ( tx_sample && tx_finished && tx_byte_cnt < 60 ) // check if we need to pad?
tx_state <= TX_ST_5;
- else if ( tx_sample && (tx_fifo_empty || tx_last_byte) ) // check if we're done
+ else if ( tx_sample && tx_finished) // check if we're done
tx_state <= TX_ST_6;
TX_ST_5: if ( tx_sample && tx_byte_cnt >= 60 ) // pad state, test for sufficient frame size
tx_state <= TX_ST_6;
@@ -662,19 +679,18 @@ always @(posedge clk, negedge rstn)
default: tx_state <= tx_state;
endcase
end
-
-
-
/*
* tx related data mux and control signals
+* TODO: add additional states for stuffing header values
+* TODO: this will need to be registered at some point
*
*/
always @(*)
begin
tx_f_pkt = 1'b0;
tx_k_pkt = 1'b0;
- tx_disp_correct = 1'b0;
+ i_tx_disp_correct = 1'b0;
tx_last_byte = 1'b0;
fcs_init = 1'b0;
fcs_addr_e = 1'b0;
@@ -698,7 +714,36 @@ always @(*)
end
TX_ST_4:
begin
- if ( tx_mode == TX_MODE_XMT_METRICS && tx_byte_cnt <= SZ_ETH_HEADER + SZ_IPV4_HEADER + SZ_UDP_HEADER )
+ if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd17) begin
+ tx_data_pkt = tx_ipv4_length[15:8];
+ fcs_dout = tx_ipv4_length[15:8];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd18) begin
+ tx_data_pkt = tx_ipv4_length[7:0];
+ fcs_dout = tx_ipv4_length[7:0];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd25) begin
+ tx_data_pkt = tx_ipv4_cksum[15:8];
+ fcs_dout = tx_ipv4_cksum[15:8];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd26) begin
+ tx_data_pkt = tx_ipv4_cksum[7:0];
+ fcs_dout = tx_ipv4_cksum[7:0];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd38) begin
+ tx_data_pkt = 8'h0 + tx_src_sel[2]; // UDP destination port
+ fcs_dout = 8'h0 + tx_src_sel[2];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd39) begin
+ tx_data_pkt = tx_udp_length[15:8];
+ fcs_dout = tx_udp_length[15:8];
+ end
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_byte_cnt == 'd40) begin
+ tx_data_pkt = tx_udp_length[7:0];
+ fcs_dout = tx_udp_length[7:0];
+ end
+ else if ( (tx_mode == TX_MODE_XMT_METRICS || tx_mode == TX_MODE_XMT_CUSTOM)
+ && tx_byte_cnt <= SZ_ETH_HEADER + SZ_IPV4_HEADER + SZ_UDP_HEADER )
begin
tx_data_pkt = dpr_di_reg[7:0]; // packet headers
fcs_dout = dpr_di_reg[7:0];
@@ -712,13 +757,14 @@ always @(*)
end
else
begin
- tx_data_pkt = tx_fifo_d_m1[7:0]; // read data from memory
+ tx_data_pkt = tx_fifo_d_m1[7:0]; // read data from FIFO
tx_last_byte = tx_fifo_d_m1[8];
end
end
TX_ST_5:
begin
- tx_data_pkt = 8'h0; // pad
+ tx_data_pkt = 8'h00; // pad
+ fcs_dout = 8'h00;
end
TX_ST_6: begin
tx_data_pkt = fcs_din; // read from fcs
@@ -751,7 +797,7 @@ always @(*)
TX_ST_C:
begin
tx_data_pkt = D16_2; // 2nd idle code
- tx_disp_correct = 1'b1; // PCS may convert D16.2 to a D5.6 for I2 to flip disparity
+ i_tx_disp_correct = 1'b1; // PCS may convert D16.2 to a D5.6 for I2 to flip disparity
tx_f_pkt = 1'b1;
end
default:
@@ -779,6 +825,8 @@ always @(*)
tx_fifo_re = 1'b1;
else
tx_fifo_re = 1'b0;
+ else if (tx_mode == TX_MODE_XMT_CUSTOM && tx_state == TX_ST_4 && tx_byte_cnt > SZ_ETH_HEADER + SZ_IPV4_HEADER + SZ_UDP_HEADER - 2)
+ tx_fifo_re = 1'b1;
else
tx_fifo_re = 1'b0;
@@ -789,7 +837,7 @@ always @(posedge clk, negedge rstn)
else if (tx_sample)
if ( mode_100Mbit && tx_state == TX_ST_1 && tx_byte_cnt == 'h5 )
param_addr <= 'h0;
- else if ( mode_1Gbit && tx_state == TX_ST_1 && tx_byte_cnt == 'h4 )
+ else if ( mode_1Gbit && tx_state == TX_ST_1 && tx_byte_cnt == 'h2 )
param_addr <= 'h0;
else
param_addr <= param_addr + 1;
@@ -858,7 +906,8 @@ always @(posedge clk or negedge rstn)
assign dpr_we = 1'b0;
assign dpr_ce = 1'b1;
-assign dpr_ad = { 4'h0, param_addr };
+assign dpr_ad = param_addr;
+assign dpr_do = 9'd0;
/*
* tx_sop, K27_7, 0xFB /S/ Start_of_Packet
@@ -867,7 +916,7 @@ assign dpr_ad = { 4'h0, param_addr };
always @(posedge clk or negedge rstn)
if (!rstn)
tx_sop <=1'b0;
- else if ( tx_state == TX_ST_0 && tx_mode == TX_MODE_XMT_PKT )
+ else if ( tx_state == TX_ST_0 && tx_mode >= TX_MODE_XMT_PKT )
tx_sop <= 1'b1;
else
tx_sop <= 1'b0;
@@ -883,11 +932,40 @@ always @(posedge clk or negedge rstn)
else
tx_eop <= 1'b0;
+// Layer 3 TX Support
+always @(posedge clk or negedge rstn)
+ if (!rstn)
+ tx_ipv4_length <= 16'h0000;
+ else if ( tx_state == TX_ST_1 )
+ tx_ipv4_length <= {5'h00, tx_byte_cnt_i} +SZ_IPV4_HEADER + SZ_UDP_HEADER;
+
+// tx_ipv4_cksum
+always @(posedge clk or negedge rstn)
+ if (!rstn)
+ tx_ipv4_cksum <= 18'h00000;
+ else if ( tx_state == TX_ST_2 )
+ tx_ipv4_cksum <= {10'h000, dpr_di_reg[7:0]};
+ else if ( tx_state == TX_ST_3 )
+ tx_ipv4_cksum <= {2'b00, dpr_di_reg[7:0], tx_ipv4_cksum[7:0]};
+ else if (tx_state == TX_ST_4 && tx_byte_cnt == 'd1)
+ tx_ipv4_cksum <= tx_ipv4_cksum + tx_ipv4_length;
+ else if (tx_state == TX_ST_4 && tx_byte_cnt == 'd2)
+ tx_ipv4_cksum <= {2'b00,tx_ipv4_cksum[15:0]} + {16'h0000,tx_ipv4_cksum[17:16]};
+ else if (tx_state == TX_ST_4 && tx_byte_cnt == 'd3)
+ tx_ipv4_cksum <= {2'b00, ~tx_ipv4_cksum[15:0]};
+
+// Layer 4 TX Support
+always @(posedge clk or negedge rstn)
+ if (!rstn)
+ tx_udp_length <= 16'h0000;
+ else if ( tx_state == TX_ST_1 )
+ tx_udp_length <= {5'h00, tx_byte_cnt_i} + SZ_UDP_HEADER;
+
/* Debug TX */
always @(posedge clk or negedge rstn)
if (!rstn)
tx_active <=1'b0;
- else if ( tx_state != 0 )
+ else if ( tx_state == TX_ST_1 )
tx_active <= 1'b1;
else
tx_active <= 1'b0;

Highly Recommended Verilog Books