URL
https://opencores.org/ocsvn/sgmii/sgmii/trunk
Subversion Repositories sgmii
[/] [sgmii/] [trunk/] [sim/] [BFMs/] [SGMII_altera/] [testbench/] [model/] [ethmon.v] - Rev 27
Go to most recent revision | Compare with Previous | Blame | View Log
// ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // // Revision Control Information // // $RCSfile: ethmon.v,v $ // $Source: /ipbu/cvs/sio/projects/TriSpeedEthernet/src/testbench/models/verilog/ethernet_model/mon/ethmon.v,v $ // // $Revision: #1 $ // $Date: 2012/06/21 $ // Check in by : $Author: swbranch $ // Author : SKNg/TTChong // // Project : Triple Speed Ethernet - 10/100/1000 MAC // // Description : (Simulation only) // // GMII Interface Ethernet Traffic Monitor/Decoder // Ethernet Traffic Monitor for 8 bit MAC Atlantic client interface // // // ALTERA Confidential and Proprietary // Copyright 2006 (c) Altera Corporation // All rights reserved // // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- `timescale 1 ns / 1 ns module ethmonitor ( reset, tx_clk, txd, tx_dv, tx_er, tx_sop, tx_eop, dst, src, prmble_len, pquant, vlan_ctl, len, frmtype, payload, payload_vld, is_vlan, is_stack_vlan, is_pause, crc_err, prmbl_err, len_err, payload_err, frame_err, pause_op_err, pause_dst_err, mac_err, end_err, jumbo_en, data_only, frm_rcvd); parameter ENABLE_SHIFT16 = 1'b 0; input reset; // active high input tx_clk; input [7:0] txd; input tx_dv; input tx_er; input tx_sop; input tx_eop; output [47:0] dst; // destination address output [47:0] src; // source address output [13:0] prmble_len; // length of preamble output [15:0] pquant; // Pause Quanta value output [15:0] vlan_ctl; // VLAN control info output [15:0] len; // Length of payload output [15:0] frmtype; // if non-null: type field instead length output [7:0] payload; output payload_vld; output is_vlan; output is_stack_vlan; output is_pause; output crc_err; output prmbl_err; output len_err; output payload_err; output frame_err; output pause_op_err; output pause_dst_err; output mac_err; output end_err; input jumbo_en; input data_only; output frm_rcvd; // GMII transmit interface: To be connected to MAC TX wire [47:0] dst; reg [47:0] src; wire [13:0] prmble_len; reg [15:0] pquant; reg [15:0] vlan_ctl; wire [15:0] len; wire [15:0] frmtype; reg [7:0] payload; // Indicators reg payload_vld; wire is_vlan; wire is_stack_vlan; wire is_pause; reg crc_err; reg prmbl_err; reg len_err; reg payload_err; reg frame_err; reg pause_op_err; reg pause_dst_err; reg mac_err; // Control reg end_err; reg frm_rcvd; reg frm_in; reg tx_clk_int; reg tx_eop_reg; // port signals internally reused reg [13:0] iprmble_len; // length of preamble reg [15:0] ifrmtype; reg [15:0] ilen; reg [47:0] idst; reg iis_vlan; reg iis_stack_vlan; reg iis_pause; reg tx_clk_dly; // internal // TYPE state_typ: parameter state_typ_s_idle = 0; parameter state_typ_s_prmbl = 1; parameter state_typ_s_dst = 2; parameter state_typ_s_src = 3; parameter state_typ_s_typelen = 4; parameter state_typ_s_pause = 5; parameter state_typ_s_tag = 6; parameter state_typ_s_len = 7; parameter state_typ_s_data = 8; parameter state_typ_s_pad = 9; parameter state_typ_s_crc = 10; parameter state_typ_s_abort = 11; parameter state_typ_s_utype = 12; parameter state_typ_s_Dword32Aligned = 13; reg [3:0] state; reg [3:0] last_state; reg last_tx_dv; // follows tx_dv with one cycle delay reg [31:0] crc32; reg [31:0] count; reg [31:0] poscnt; // position in frame starts at first dst byte reg [7:0] datacnt; // counter to verify payload reg [7:0] datainc; // counter increment reg tx_sof; // start of frame indicator for 1 clk cycle with 1st byte reg tx_dst; // start of frame indicator for 1 clk cycle with 1st byte reg [31:0] process_6_crctmp; reg [3:0] V2V_process_6_i; integer process_11_ix; integer process_12_ix; reg process_12_ln; integer process_14_hi; integer process_14_lo; reg [31:0] process_14_cnttmp; integer process_14_i; integer process_14_flen; always @(posedge reset or posedge tx_clk) begin : process_1 if (reset == 1'b 1) begin tx_eop_reg <= 1'b 0; end else begin tx_eop_reg <= tx_eop; end end always @(tx_sop or tx_eop_reg) begin : process_2 if (tx_sop == 1'b 1 & data_only == 1'b 1) begin frm_in <= 1'b 1; end else if (tx_eop_reg == 1'b 1 ) begin frm_in <= 1'b 0; end end always@(tx_clk) begin tx_clk_dly <= #(1)tx_clk ; end always @(frm_in or tx_dv or tx_clk_dly) begin : process_3 if (frm_in == 1'b 1 && tx_dv == 1'b 1 ) begin tx_clk_int <= #(1) tx_clk_dly; end else if (frm_in==1'b1 && tx_dv == 1'b 0) begin tx_clk_int <= #(1) 1'b 0; end else begin tx_clk_int <= #(1) tx_clk_dly; end end // connect permanent port signals // ------------------------------ assign prmble_len = iprmble_len; assign frmtype = ifrmtype; assign len = ilen; assign dst = idst; assign is_vlan = iis_vlan; assign is_stack_vlan = iis_stack_vlan; assign is_pause = iis_pause; // generate tx start pulse // ---------------------- always@(last_tx_dv or tx_dv or tx_sop) begin if (data_only==1'b0) begin tx_sof <= ~last_tx_dv & tx_dv; // pulse with first byte 0 to 1 change end else begin tx_sof <= tx_sop ; end end // generate pulse start of destination address // -------------------- always @(last_state or state) begin : process_4 if (last_state != state_typ_s_dst & state == state_typ_s_dst) begin tx_dst <= 1'b 1; end else begin tx_dst <= 1'b 0; end end // ------------------------------------------ // capture tx_er indicator // ------------------------------------------ always @(posedge tx_clk_int or posedge reset) begin : process_5 if (reset == 1'b 1) begin mac_err <= 1'b 0; last_tx_dv <= 1'b 0; end else begin if (tx_sof == 1'b 1) begin mac_err <= 1'b 0; // reset indicator at start of new receive end else if (tx_er == 1'b 1 ) begin mac_err <= 1'b 1; // capture one or many end last_tx_dv <= tx_dv; end end // ---------------------------------------------- // CRC calculation over all bytes except preamble // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_6 if (reset == 1'b 1) begin crc32 <= {32{1'b 1}}; crc_err <= 1'b 0; end else begin // need it ahead if (tx_dst == 1'b 1 | state != state_typ_s_idle & state != state_typ_s_prmbl & state != state_typ_s_utype | state == state_typ_s_utype & tx_dv == 1'b 1) begin // push all inclusive CRC bytes // preset CRC or load current value if (tx_dst == 1'b 1) begin // first data, preset CRC process_6_crctmp = {32{1'b 1}}; end else begin process_6_crctmp = crc32; end // calculate next step for (V2V_process_6_i = 0; V2V_process_6_i <= 7; V2V_process_6_i = V2V_process_6_i + 1) begin if ((txd[V2V_process_6_i] ^ process_6_crctmp[31]) == 1'b 1) begin process_6_crctmp = (process_6_crctmp << 1); // shift in a 0, will be xor'ed to 1 by the polynom process_6_crctmp = process_6_crctmp ^ 32'h 04C11DB7; end else begin process_6_crctmp = (process_6_crctmp << 1); // shift in a 0 end end // process all bits we have here crc32 <= process_6_crctmp; // remember current value // check if CRC is valid if (process_6_crctmp == 32'h C704DD7B) begin crc_err <= 1'b 0; end else begin crc_err <= 1'b 1; end end end end // ---------------------------------------------- // Extract RX Payload on payload bus and check payload errors: // * first byte is counter initialization // * second byte is counter increment // * data begins from 3rd byte on // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_7 if (reset == 1'b 1) begin payload <= {8{1'b 0}}; payload_vld <= 1'b 0; payload_err <= 1'b 0; datacnt <= 0; end else begin if (state == state_typ_s_typelen) begin payload_err <= 1'b 0; // reset as a frame of length 0 will not get into S_DATA. end if (state == state_typ_s_data) begin payload <= txd; payload_vld <= 1'b 1; if (count == 0) begin datacnt <= ({1'b 0, txd}); // load counter payload_err <= 1'b 0; end else if (count == 1 ) begin datainc <= ({1'b 0, txd}); // load increment // verify payload contents end else begin datacnt <= (datacnt + datainc) % 256; if (datacnt != ({1'b 0, txd})) begin payload_err <= 1'b 1; end end end else begin payload <= {8{1'b 0}}; payload_vld <= 1'b 0; end end end // ---------------------------------------------- // Position Counter: Starts with first octet of destination address // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_8 if (reset == 1'b 1) begin poscnt <= 0; end else begin if (tx_dst == 1'b 1) begin // reset at start of DST poscnt <= 1; end else begin if (poscnt < 65535) begin poscnt <= poscnt + 1'b 1; end end end end // ---------------------------------------------- // End of Frame: // change from non-idle to idle indicates something was received // if dv is still asserted this is an end error // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_9 if (reset == 1'b 1) begin frm_rcvd <= 1'b 0; end_err <= 1'b 0; end else begin if (last_state != state_typ_s_idle & state == state_typ_s_idle) begin frm_rcvd <= 1'b 1; end else begin frm_rcvd <= 1'b 0; end if (tx_sof == 1'b 1) begin end_err <= 1'b 0; end else if (last_state != state_typ_s_idle & state == state_typ_s_idle & tx_dv == 1'b 1 ) begin end_err <= 1'b 1; // dv still asserted even after nothing more expected end end end // ---------------------------------------------- // Preamble check // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_10 if (reset == 1'b 1) begin prmbl_err <= 1'b 0; iprmble_len <= 0; end else begin if (tx_sof == 1'b 1) begin if (txd != 8'h 55) begin prmbl_err <= 1'b 1; end else begin prmbl_err <= 1'b 0; // reset usually end if (data_only == 1'b 1) begin iprmble_len <= 0; end else begin iprmble_len <= 1; end end else if (state == state_typ_s_prmbl ) begin if (txd != 8'h 55 & txd != 8'h D5) begin prmbl_err <= 1'b 1; end iprmble_len <= iprmble_len + 1'b 1; end end end // ---------------------------------------------- // Extract Source and Destination addresses // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_11 if (reset == 1'b 1) begin idst <= {48{1'b 0}}; src <= {48{1'b 0}}; end else begin process_11_ix = count * 8; if (tx_sof == 1'b 1) begin process_11_ix = 1'b 0; end if (tx_sof == 1'b 1 & data_only == 1'b 1 & state == state_typ_s_Dword32Aligned & ENABLE_SHIFT16 == 1'b1) begin case (count) 1'b 0 : ; 1'b 1 : ; default:; endcase end if (tx_sof == 1'b 0 & data_only == 1'b 1 & ENABLE_SHIFT16 == 1'b1 & state == state_typ_s_dst) begin case (count) 1'b 0: begin idst[7:0] <= txd[7:0]; end 1'b 1: begin idst[15:8] <= txd[7:0]; end 2'b 10: begin idst[23:16] <= txd[7:0]; end 2'b 11: begin idst[31:24] <= txd[7:0]; end 3'b 100: begin idst[39:32] <= txd[7:0]; end 3'b 101: begin idst[47:40] <= txd[7:0]; end default: ; endcase end if (tx_sof == 1'b 1 & data_only == 1'b 1 & ENABLE_SHIFT16 == 1'b0| state == state_typ_s_dst) begin case (count) 1'b 0: begin idst[7:0] <= txd[7:0]; end 1'b 1: begin idst[15:8] <= txd[7:0]; end 2'b 10: begin idst[23:16] <= txd[7:0]; end 2'b 11: begin idst[31:24] <= txd[7:0]; end 3'b 100: begin idst[39:32] <= txd[7:0]; end 3'b 101: begin idst[47:40] <= txd[7:0]; end default: ; endcase end if (state == state_typ_s_src) begin case (count) 1'b 0: begin src[7:0] <= txd[7:0]; end 1'b 1: begin src[15:8] <= txd[7:0]; end 2'b 10: begin src[23:16] <= txd[7:0]; end 2'b 11: begin src[31:24] <= txd[7:0]; end 3'b 100: begin src[39:32] <= txd[7:0]; end 3'b 101: begin src[47:40] <= txd[7:0]; end default: ; endcase end end end // ---------------------------------------------- // Extract Length/Type field and VLAN Tag identifier // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_12 if (reset == 1'b 1) begin ilen <= {16{1'b 0}}; ifrmtype <= {16{1'b 0}}; vlan_ctl <= {16{1'b 0}}; iis_vlan <= 1'b 0; len_err <= 1'b 0; iis_stack_vlan <= 1'b0; end else begin process_12_ix = 4'b 1000 - count * 8; // if( tx_sof_d = '1' ) then -- clear all on start of every frame // // ilen <= (others => '0'); // ifrmtype <= (others => '0'); // vlan_ctl <= (others => '0'); // iis_vlan <= '0'; // // end if; if (state == state_typ_s_typelen) begin // if in type/len set both case (count) 1'b 0: begin ifrmtype[15:8] <= txd; ilen[15:8] <= txd; end 1'b 1: begin ifrmtype[7:0] <= txd; ilen[7:0] <= txd; end default: ; endcase vlan_ctl <= {16{1'b 0}}; // clear at start of new frame (at SOF it is too early) iis_vlan <= 1'b 0; len_err <= 1'b 0; end if(state==state_typ_s_typelen) begin iis_stack_vlan <= 1'b0 ; end else if (last_state == state_typ_s_len & state == state_typ_s_tag) begin iis_stack_vlan <= 1'b1 ; end else if (state == state_typ_s_len ) begin // in len again, set len independently case (count) 1'b 0: begin ifrmtype[15:8] <= txd; ilen[15:8] <= txd; end 1'b 1: begin ifrmtype[7:0] <= txd; ilen[7:0] <= txd; end default: ; endcase end else if (state == state_typ_s_tag ) begin iis_vlan <= 1'b 1; case (count) 1'b 0: begin vlan_ctl[15:8] <= txd; // ilen(ix+7 downto ix) <= txd; end 1'b 1: begin vlan_ctl[7:0] <= txd; end default: ; endcase end // verify length at end of frame for normal frames (length 46... max and not a type) if (last_state == state_typ_s_crc & state == state_typ_s_idle & iis_pause == 1'b 0 & (iis_vlan == 1'b 0 & ilen > 45 | iis_vlan == 1'b 1 & ilen > 41)) begin // verify integrity of length field if (tx_dv == 1'b 1 | iis_stack_vlan == 1'b 1 & ilen != poscnt - 5'b 11010 | (iis_vlan == 1'b 1 & iis_stack_vlan == 1'b 0) & ilen != poscnt - 5'b 10110 | iis_vlan == 1'b 0 & ilen != poscnt - 5'b 10010) begin len_err <= 1'b 1; end else begin len_err <= 1'b 0; end end end end // ---------------------------------------------- // Extract Pause frame indication, // opcode error, // destination address error, // and Pause Quanta // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_13 if (reset == 1'b 1) begin pquant <= {16{1'b 0}}; iis_pause <= 1'b 0; pause_op_err <= 1'b 0; pause_dst_err <= 1'b 0; end else begin if (tx_sof == 1'b 1) begin iis_pause <= 1'b 0; // clear at start of frame pause_op_err <= 1'b 0; pause_dst_err <= 1'b 0; end if (state == state_typ_s_pause) begin iis_pause <= 1'b 1; //if (count >= 2) //begin // pick octets after opcode case (count) 2'b 10: begin pquant[15:8] <= txd; end 2'b 11: begin pquant[7:0] <= txd; end default: ; endcase //end if (count == 0 & txd != 8'h 00 | count == 1 & txd != 8'h 01 ) begin pause_op_err <= 1'b 1; end if (idst != 48'h 010000c28001) begin // 01-80-c2-00-00-01 is standard ! pause_dst_err <= 1'b 1; end end end end // ---------------------------------------------- // Monitor State Machine // ---------------------------------------------- always @(posedge tx_clk_int or posedge reset) begin : process_14 if (reset == 1'b 1) begin state <= state_typ_s_idle; last_state <= state_typ_s_idle; count <= 0; frame_err <= 1'b 0; // state machine abort indicator end else begin // remember last state and increment internal counter last_state <= state; if (count < 65535) begin process_14_cnttmp = count + 1'b 1; end else begin process_14_cnttmp = count; end // Abort detection: If enable goes low in middle of frame if (state != state_typ_s_idle & state != state_typ_s_abort & state != state_typ_s_utype & tx_dv == 1'b 0) begin state <= state_typ_s_abort; end else begin case (state) state_typ_s_abort: begin if (tx_dv == 1'b 1) begin if (last_tx_dv == 1'b 0 & data_only == 1'b 1) begin // only 1 clock cycle inbetween if (ENABLE_SHIFT16 == 1'b0) state <= state_typ_s_dst; else state <= state_typ_s_Dword32Aligned; process_14_cnttmp = 1'b 1; frame_err <= 1'b 0; end else begin state <= state_typ_s_abort; // wait til tx stops transmission end end else begin state <= state_typ_s_idle; end frame_err <= 1'b 1; end state_typ_s_idle: begin if (tx_sof == 1'b 1) begin // we miss the very first ! process_14_cnttmp = 1'b 1; // therefore need to count to 1 immediately frame_err <= 1'b 0; if (data_only == 1'b 1) begin // no preamble checking ? if (ENABLE_SHIFT16 == 1'b0) state <= state_typ_s_dst; else state <= state_typ_s_Dword32Aligned; end else begin state <= state_typ_s_prmbl; end end else begin process_14_cnttmp = 1'b 0; // keep it to zero always end end state_typ_s_prmbl: begin if (txd == 8'h D5) begin state <= state_typ_s_dst; process_14_cnttmp = 1'b 0; end end state_typ_s_Dword32Aligned: begin if (count == 1) begin state <= state_typ_s_dst; process_14_cnttmp = 1'b 0; end end state_typ_s_dst: begin if (count == 5) begin state <= state_typ_s_src; process_14_cnttmp = 1'b 0; end end state_typ_s_src: begin if (count == 5) begin state <= state_typ_s_typelen; process_14_cnttmp = 1'b 0; end end state_typ_s_typelen: begin if (count != 0) begin // second half of 2-octet field process_14_cnttmp = 1'b 0; process_14_flen = ({1'b 0, ilen[15:8], txd}); // need it NOW if (process_14_flen <= 1500) begin // ok normal user frame. check if data or 0 length if (process_14_flen != 0) begin state <= state_typ_s_data; // no data, PAD or finished end else begin if (data_only == 1'b 1) begin state <= state_typ_s_idle; // Ok, we are done dont expect anything more end else begin state <= state_typ_s_pad; // zero-length frame needs padding end end // not normal frame end else begin if (process_14_flen == 16'h 8808) begin state <= state_typ_s_pause; end else if (process_14_flen == 16'h 8100 ) begin state <= state_typ_s_tag; end else begin state <= state_typ_s_utype; // S_ABORT; -- unknown type end end end end state_typ_s_pause: begin if (count >= 3) begin // need to overread opcode state <= state_typ_s_pad; process_14_cnttmp = 1'b 0; end end state_typ_s_tag: begin if (count >= 1) begin state <= state_typ_s_len; process_14_cnttmp = 1'b 0; end end state_typ_s_len: begin if (count >= 1) begin // Length after VLAN TAG process_14_cnttmp = 1'b 0; process_14_flen = ({1'b 0, ilen[15:8], txd}); // need it NOW if ( process_14_flen == 16'h8100) begin state <= state_typ_s_tag; end else if (process_14_flen != 0) begin state <= state_typ_s_data; // no data, PAD or finished end else begin if (data_only == 1'b 1) begin state <= state_typ_s_idle; // Ok, we are done dont expect CRC end else begin state <= state_typ_s_pad; end end end end state_typ_s_data: begin if (count >= ilen - 1'b 1) begin process_14_cnttmp = 1'b 0; if (data_only == 1'b 1) begin // no PAD and no CRC ? state <= state_typ_s_idle; end else if (poscnt < 6'b 111100 - 1'b 1 ) begin // expect padding ? state <= state_typ_s_pad; end else begin state <= state_typ_s_crc; end end end state_typ_s_pad: begin if (poscnt >= 6'b 111100 - 1'b 1) begin state <= state_typ_s_crc; process_14_cnttmp = 1'b 0; end end state_typ_s_crc: begin if (count >= 3) begin state <= state_typ_s_idle; process_14_cnttmp = 1'b 0; end end state_typ_s_utype: begin if (tx_dv == 1'b 0) begin // unknown type... wait for end of frame state <= state_typ_s_idle; process_14_cnttmp = 1'b 0; end end endcase end // abort // load the counter with the new value count <= process_14_cnttmp; end end endmodule // module ethmonitor
Go to most recent revision | Compare with Previous | Blame | View Log