OpenCores
URL https://opencores.org/ocsvn/esoc/esoc/trunk

Subversion Repositories esoc

[/] [esoc/] [trunk/] [Sources/] [altera/] [esoc_port_mac/] [testbench/] [model/] [ethmon.vhd] - Blame information for rev 47

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 42 lmaarsen
-- -------------------------------------------------------------------------
2
-- -------------------------------------------------------------------------
3
--
4
-- Revision Control Information
5
--
6
-- $RCSfile: ethmon.vhd,v $
7
-- $Source: /ipbu/cvs/sio/projects/TriSpeedEthernet/src/testbench/models/vhdl/ethernet_model/mon/ethmon.vhd,v $
8
--
9
-- $Revision: #1 $
10
-- $Date: 2008/08/09 $
11
-- Check in by : $Author: sc-build $
12
-- Author      : SKNg/TTChong
13
--
14
-- Project     : Triple Speed Ethernet - 10/100/1000 MAC
15
--
16
-- Description : (Simulation only)
17
--
18
-- GMII Interface Ethernet Traffic Monitor/Decoder
19
-- Ethernet Traffic Monitor for 8 bit MAC Atlantic client interface
20
--
21
-- 
22
-- ALTERA Confidential and Proprietary
23
-- Copyright 2006 (c) Altera Corporation
24
-- All rights reserved
25
--
26
-- -------------------------------------------------------------------------
27
-- -------------------------------------------------------------------------
28
 
29
library ieee ;
30
use ieee.std_logic_1164.all ;
31
use ieee.std_logic_arith.all ;
32
use ieee.std_logic_unsigned.all ;
33
use std.textio.all ;
34
 
35
entity ETHMONITOR is
36
 
37
    generic (  ENABLE_SHIFT16 : integer := 0  --0 for false, 1 for true
38
                        );
39
 
40
    port (
41
 
42
      reset       : in std_logic ;     -- active high
43
 
44
        -- GMII transmit interface: To be connected to MAC TX
45
 
46
      tx_clk      : in std_logic ;
47
      txd         : in std_logic_vector(7 downto 0);
48
      tx_dv       : in std_logic;
49
      tx_er       : in std_logic;
50
      tx_sop      : in std_logic;
51
      tx_eop      : in std_logic;
52
 
53
        -- Frame Contents definitions
54
 
55
      dst           : out std_logic_vector(47 downto 0); -- destination address
56
      src           : out std_logic_vector(47 downto 0); -- source address
57
 
58
      prmble_len    : out integer range 0 to 10000;         -- length of preamble
59
      pquant        : out std_logic_vector(15 downto 0); -- Pause Quanta value
60
      vlan_ctl      : out std_logic_vector(15 downto 0); -- VLAN control info
61
      len           : out std_logic_vector(15 downto 0); -- Length of payload
62
      frmtype       : out std_logic_vector(15 downto 0); -- if non-null: type field instead length
63
 
64
      payload       : out std_logic_vector(7 downto 0);
65
      payload_vld   : out std_logic;
66
 
67
        -- Indicators
68
 
69
      is_vlan       : out std_logic;
70
      is_stack_vlan : out std_logic;
71
      is_pause      : out std_logic;
72
      crc_err       : out std_logic;
73
      prmbl_err     : out std_logic;
74
      len_err       : out std_logic;
75
      payload_err   : out std_logic;
76
      frame_err     : out std_logic;
77
      pause_op_err  : out std_logic;
78
      pause_dst_err : out std_logic;
79
      mac_err       : out std_logic;
80
      end_err       : out std_logic;
81
 
82
       -- Control
83
 
84
      jumbo_en      : in std_logic;
85
      data_only     : in std_logic;
86
 
87
        -- Receive indicator
88
 
89
      frm_rcvd     : out std_logic );
90
 
91
end ETHMONITOR ;
92
 
93
architecture behave of ETHMONITOR is
94
 
95
        signal frm_in     : std_logic := '0' ;
96
        signal tx_clk_int : std_logic ;
97
        signal tx_eop_reg : std_logic ;
98
 
99
    -- port signals internally reused
100
 
101
    signal iprmble_len    : integer range 0 to 10000;         -- length of preamble
102
    signal ifrmtype       : std_logic_vector(15 downto 0);
103
    signal ilen           : std_logic_vector(15 downto 0);
104
    signal idst           : std_logic_vector(47 downto 0);
105
 
106
    signal iis_vlan       : std_logic;
107
    signal iis_stack_vlan : std_logic;
108
    signal iis_pause      : std_logic;
109
 
110
    -- internal
111
 
112
    type  state_typ is (S_IDLE, S_PRMBL,
113
                                S_DST , S_SRC, S_TYPELEN, S_PAUSE, S_TAG, S_LEN,
114
                                S_DATA, S_PAD, S_CRC, S_ABORT, S_UTYPE, S_Dword32Aligned);
115
 
116
    signal state      : state_typ;
117
    signal last_state : state_typ;
118
 
119
 
120
    signal last_tx_dv : std_logic;     -- follows tx_dv with one cycle delay
121
 
122
 
123
    signal crc32 : std_logic_vector(31 downto 0);
124
 
125
    signal count : integer range 0 to 65535;
126
    signal poscnt: integer range 0 to 65535;       -- position in frame starts at first dst byte
127
 
128
    signal datacnt: integer range 0 to 255;   -- counter to verify payload
129
    signal datainc: integer range 0 to 255;   -- counter increment
130
 
131
    signal tx_sof  :  std_logic;   -- start of frame indicator for 1 clk cycle with 1st byte
132
    signal tx_dst  :  std_logic;   -- start of frame indicator for 1 clk cycle with 1st byte
133
 
134
 
135
begin
136
 
137
        process(reset, tx_clk)
138
        begin
139
 
140
                if (reset='1') then
141
 
142
                        tx_eop_reg <= '0' ;
143
 
144
                elsif (tx_clk='1') and (tx_clk'event) then
145
 
146
                        tx_eop_reg <= tx_eop ;
147
 
148
                end if ;
149
 
150
        end process ;
151
 
152
        process(tx_sop, tx_eop)
153
        begin
154
 
155
                if (tx_sop='1' and data_only='1') then
156
 
157
                        frm_in <= '1' ;
158
 
159
                elsif (tx_eop_reg='1') then
160
 
161
                        frm_in <= '0' ;
162
 
163
                end if ;
164
 
165
        end process ;
166
 
167
        process(frm_in, tx_dv, tx_clk)
168
        begin
169
 
170
                if (frm_in='1' and tx_dv='1') then
171
 
172
                        tx_clk_int <= tx_clk after 1 ns ;
173
 
174
                elsif (frm_in='1' and tx_dv='0') then
175
 
176
                        tx_clk_int <= '0' after 1 ns  ;
177
 
178
                else
179
 
180
                        tx_clk_int <= tx_clk after 1 ns ;
181
 
182
                end if ;
183
 
184
        end process ;
185
 
186
    -- connect permanent port signals
187
    -- ------------------------------
188
 
189
    prmble_len    <= iprmble_len;
190
    frmtype       <= ifrmtype;
191
    len           <= ilen;
192
    dst           <= idst;
193
    is_vlan       <= iis_vlan;
194
    is_stack_vlan <= iis_stack_vlan;
195
    is_pause      <= iis_pause;
196
 
197
 
198
    -- generate tx start pulse
199
    -- ----------------------
200
 
201
    tx_sof <= (not(last_tx_dv) and tx_dv) when (data_only='0') else tx_sop;     -- pulse with first byte 0 to 1 change
202
 
203
 
204
    -- generate pulse start of destination address
205
    -- --------------------
206
 
207
    process( last_state, state )
208
    begin
209
 
210
        if( (last_state/=S_DST) and (state=S_DST)) then
211
 
212
            tx_dst <= '1';
213
 
214
        else
215
 
216
            tx_dst <= '0';
217
 
218
        end if;
219
   end process;
220
 
221
 
222
    -- ------------------------------------------
223
    -- capture tx_er indicator
224
    -- ------------------------------------------
225
 
226
    process( tx_clk_int, reset )
227
    begin
228
 
229
        if( reset='1') then
230
 
231
            mac_err    <= '0';
232
            last_tx_dv <= '0';
233
 
234
        elsif( tx_clk_int='1' and tx_clk_int'event ) then
235
 
236
            if( tx_sof='1' ) then
237
 
238
                mac_err <= '0';            -- reset indicator at start of new receive
239
 
240
            elsif( tx_er = '1' ) then
241
 
242
                mac_err <= '1';        -- capture one or many
243
 
244
            end if;
245
 
246
            last_tx_dv <= tx_dv;
247
 
248
        end if;
249
    end process;
250
 
251
 
252
    -- ----------------------------------------------
253
    -- CRC calculation over all bytes except preamble
254
    -- ----------------------------------------------
255
 
256
    process( tx_clk_int, reset )
257
 
258
        variable crctmp : std_logic_vector(31 downto 0);
259
        variable i      : integer range 0 to 8;
260
 
261
    begin
262
        if( reset = '1' ) then
263
 
264
            crc32    <= (others => '1' );
265
            crc_err  <= '0';
266
 
267
        elsif( tx_clk_int = '1' and tx_clk_int'event ) then    -- need it ahead
268
 
269
            if( (tx_dst='1') or
270
                ((state /= S_IDLE) and (state /= S_PRMBL) and (state /= S_UTYPE)) or
271
                ((state = S_UTYPE) and tx_dv='1') ) then  -- push all inclusive CRC bytes
272
 
273
                    -- preset CRC or load current value
274
 
275
                    if( tx_dst='1' ) then   -- first data, preset CRC
276
 
277
                        crctmp := (others => '1' );
278
 
279
                    else
280
 
281
                        crctmp := crc32;
282
 
283
                    end if;
284
 
285
                    -- calculate next step
286
 
287
                    for i in 0 to 7 loop      -- process all bits we have here
288
 
289
                       if( (txd(i) xor crctmp(31)) = '1' ) then
290
                         crctmp := to_stdlogicvector((to_bitvector(crctmp)) sll 1);  -- shift in a 0, will be xor'ed to 1 by the polynom
291
                         crctmp := crctmp xor X"04C11DB7";
292
                       else
293
                         crctmp := to_stdlogicvector((to_bitvector(crctmp)) sll 1);  -- shift in a 0
294
                       end if;
295
 
296
                   end loop;
297
 
298
                   crc32 <= crctmp; -- remember current value
299
 
300
 
301
                   -- check if CRC is valid
302
 
303
                   if( crctmp = X"C704DD7B" ) then
304
 
305
                        crc_err <= '0';
306
 
307
                   else
308
 
309
                        crc_err <= '1';
310
 
311
                   end if;
312
 
313
            end if;
314
 
315
        end if;
316
 
317
    end process;
318
 
319
    -- ----------------------------------------------
320
    -- Extract RX Payload on payload bus and check payload errors:
321
    -- * first byte is counter initialization
322
    -- * second byte is counter increment
323
    -- * data begins from 3rd byte on 
324
    -- ----------------------------------------------
325
 
326
    process( tx_clk_int, reset )
327
    begin
328
        if( reset = '1' ) then
329
 
330
            payload     <= (others => '0' );
331
            payload_vld <= '0';
332
            payload_err <= '0';
333
            datacnt     <= 0;
334
 
335
        elsif( tx_clk_int='1' and tx_clk_int'event ) then
336
 
337
            if( state = S_TYPELEN ) then
338
 
339
                payload_err <= '0';        -- reset as a frame of length 0 will not get into S_DATA.
340
 
341
            end if;
342
 
343
            if( state = S_DATA) then
344
 
345
                payload     <= txd;
346
                payload_vld <= '1';
347
 
348
                if( count=0 ) then
349
 
350
                    datacnt <= conv_integer('0' & txd);   -- load counter
351
                    payload_err <= '0';
352
 
353
                elsif( count=1) then
354
 
355
                    datainc <= conv_integer('0' & txd);   -- load increment
356
 
357
                else
358
 
359
                        -- verify payload contents
360
 
361
                    datacnt <= (datacnt+datainc) mod 256;
362
 
363
                    if( datacnt /= conv_integer('0' & txd ) ) then
364
 
365
                         payload_err <= '1';
366
 
367
                    end if;
368
 
369
                end if;
370
 
371
            else
372
 
373
                payload       <= (others => '0' );
374
                payload_vld   <= '0';
375
 
376
            end if;
377
        end if;
378
    end process;
379
 
380
    -- ----------------------------------------------
381
    -- Position Counter: Starts with first octet of destination address
382
    -- ----------------------------------------------
383
 
384
    process( tx_clk_int, reset )
385
    begin
386
      if( reset = '1' ) then
387
 
388
            poscnt <= 0;
389
 
390
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
391
 
392
            if( tx_dst='1' ) then  -- reset at start of DST 
393
 
394
                poscnt <= 1;
395
 
396
            else
397
 
398
                if( poscnt < 65535 ) then
399
 
400
                        poscnt <= poscnt +1;
401
 
402
                end if;
403
 
404
            end if;
405
     end if;
406
    end process;
407
 
408
 
409
    -- ----------------------------------------------
410
    -- End of Frame:
411
    -- change from non-idle to idle indicates something was received
412
    -- if dv is still asserted this is an end error
413
    -- ----------------------------------------------
414
    process( tx_clk_int, reset )
415
    begin
416
      if( reset = '1' ) then
417
 
418
            frm_rcvd <= '0';
419
            end_err  <= '0';
420
 
421
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
422
 
423
            if( last_state/=S_IDLE and state=S_IDLE ) then
424
 
425
                frm_rcvd <= '1';
426
 
427
            else
428
 
429
                frm_rcvd <= '0';
430
 
431
            end if;
432
 
433
 
434
            if( tx_sof='1' ) then
435
 
436
                end_err <= '0';
437
 
438
            elsif(last_state/=S_IDLE and state=S_IDLE and tx_dv='1') then
439
 
440
                end_err <= '1';  -- dv still asserted even after nothing more expected
441
 
442
            end if;
443
 
444
      end if;
445
    end process;
446
 
447
    -- ----------------------------------------------
448
    -- Preamble check
449
    -- ----------------------------------------------
450
    process( tx_clk_int, reset )
451
    begin
452
      if( reset = '1' ) then
453
 
454
            prmbl_err <= '0';
455
            iprmble_len <= 0;
456
 
457
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
458
 
459
            if( tx_sof='1' ) then
460
 
461
                if( txd /= X"55" ) then
462
 
463
                    prmbl_err <= '1';
464
 
465
                else
466
 
467
                    prmbl_err <= '0';      -- reset usually
468
 
469
                end if;
470
 
471
                if( data_only='1' ) then
472
 
473
                    iprmble_len <= 0;
474
 
475
                else
476
 
477
                    iprmble_len <= 1;
478
 
479
                end if;
480
 
481
 
482
            elsif( state=S_PRMBL ) then
483
 
484
                if( txd /= X"55" and txd /= X"D5" ) then
485
 
486
                    prmbl_err <= '1';
487
 
488
                end if;
489
 
490
                iprmble_len <= iprmble_len + 1;
491
 
492
            end if;
493
      end if;
494
    end process;
495
 
496
 
497
    -- ----------------------------------------------
498
    -- Extract Source and Destination addresses
499
    -- ----------------------------------------------
500
    process( tx_clk_int, reset )
501
 
502
        variable ix: integer;
503
 
504
    begin
505
      if( reset = '1' ) then
506
 
507
            idst <= (others => '0');
508
            src <= (others => '0');
509
 
510
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
511
 
512
            ix := (count*8);
513
 
514
            if( tx_sof='1' ) then
515
                ix := 0;
516
            end if;
517
 
518
            if (tx_sof = '1' and data_only = '1' and state = S_Dword32Aligned and ENABLE_SHIFT16 = 1) then
519
                   case (count) is
520
                    when 0|1   => null ;
521
                    when others=> null ;
522
                   end case ;
523
            end if;
524
 
525
            if (tx_sof = '0' and data_only = '1' and ENABLE_SHIFT16 = 1 and state = S_DST) then
526
              idst(ix+7 downto ix) <= txd(7 downto 0);      -- first received is LSByte
527
            end if;
528
 
529
            if( (tx_sof='1' and data_only='1' and ENABLE_SHIFT16 = 0) or     -- very first byte and not preamble
530
                (state=S_DST) ) then
531
 
532
                idst(ix+7 downto ix) <= txd(7 downto 0);      -- first received is LSByte
533
 
534
            end if;
535
 
536
            if( state=S_SRC ) then
537
 
538
                src(ix+7 downto ix) <= txd(7 downto 0);      -- first received is LSByte
539
 
540
            end if;
541
 
542
      end if;
543
 
544
    end process;
545
 
546
    -- ----------------------------------------------
547
    -- Extract Length/Type field and VLAN Tag identifier
548
    -- ----------------------------------------------
549
    process( tx_clk_int, reset )
550
 
551
        variable ix: integer;
552
        variable ln: line;
553
 
554
    begin
555
      if( reset = '1' ) then
556
 
557
            ilen           <= (others => '0');
558
            ifrmtype       <= (others => '0');
559
            vlan_ctl       <= (others => '0');
560
            iis_vlan       <= '0';
561
            len_err        <= '0';
562
            iis_stack_vlan <= '0' ;
563
 
564
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
565
 
566
            ix := 8-(count*8);
567
 
568
            --if( tx_sof_d = '1' ) then              -- clear all on start of every frame
569
            --
570
            --    ilen     <= (others => '0');
571
            --    ifrmtype <= (others => '0');
572
            --    vlan_ctl <= (others => '0');
573
            --    iis_vlan  <= '0';
574
            --    
575
            --end if;
576
 
577
            if( state=S_TYPELEN ) then            -- if in type/len set both
578
 
579
                ifrmtype(ix+7 downto ix) <= txd;
580
                ilen(ix+7 downto ix)     <= txd;
581
                vlan_ctl <= (others => '0');      -- clear at start of new frame (at SOF it is too early)
582
                iis_vlan  <= '0';
583
                len_err  <= '0';
584
 
585
            elsif( state=S_LEN ) then             -- in len again, set len independently
586
 
587
                ilen(ix+7 downto ix)     <= txd;
588
 
589
            elsif( state=S_TAG ) then
590
 
591
                iis_vlan  <= '1';
592
                vlan_ctl(ix+7 downto ix) <= txd;
593
 
594
            end if;
595
 
596
            if( state=S_TYPELEN ) then
597
 
598
                iis_stack_vlan <= '0' ;
599
 
600
            elsif (last_state=S_LEN and state=S_TAG) then
601
 
602
                iis_stack_vlan <= '1' ;
603
 
604
            end if ;
605
 
606
            -- verify length at end of frame for normal frames (length 46... max and not a type)
607
 
608
            if( (last_state=S_CRC) and (state=S_IDLE) and iis_pause='0' and
609
                ( (iis_vlan='0' and (ilen > 45)) or
610
                  (iis_vlan='1' and (ilen > 41))) ) then
611
 
612
                        -- verify integrity of length field 
613
 
614
                        if( tx_dv='1' or                                 -- state machine did not expect more
615
                            (iis_stack_vlan='1' and (ilen /= (poscnt-26))) or
616
                            ((iis_vlan='1' and iis_stack_vlan='0') and (ilen /= (poscnt-22))) or
617
                            (iis_vlan='0'       and (ilen /= (poscnt-18))) ) then
618
 
619
                                len_err <= '1';
620
 
621
                        else
622
 
623
                                len_err <= '0';
624
 
625
                        end if;
626
 
627
            end if;
628
 
629
      end if;
630
   end process;
631
 
632
 
633
    -- ----------------------------------------------
634
    -- Extract Pause frame indication,
635
    --               opcode error,
636
    --               destination address error,
637
    --               and Pause Quanta
638
    -- ----------------------------------------------
639
    process( tx_clk_int, reset )
640
 
641
        variable ix: integer;
642
 
643
    begin
644
      if( reset = '1' ) then
645
 
646
            pquant       <= (others => '0');
647
            iis_pause     <= '0';
648
            pause_op_err <= '0';
649
            pause_dst_err<= '0';
650
 
651
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
652
 
653
        if( tx_sof='1' ) then
654
 
655
            iis_pause     <= '0';     -- clear at start of frame
656
            pause_op_err <= '0';
657
            pause_dst_err<= '0';
658
 
659
        end if;
660
 
661
        if( state=S_PAUSE ) then
662
 
663
            iis_pause <= '1';
664
 
665
            if( count>=2 ) then  -- pick octets after opcode
666
 
667
                ix := 8-((count-2)*8);        -- MSB comes first
668
                pquant(ix+7 downto ix) <= txd;
669
 
670
            elsif( ((count=0) and (txd/=X"00")) or       -- verify 00-01 opcode
671
                   ((count=1) and (txd/=X"01")) ) then
672
 
673
                   pause_op_err <= '1';
674
 
675
            end if;
676
 
677
            if( idst /= X"010000c28001" ) then   -- 01-80-c2-00-00-01 is standard !
678
 
679
                   pause_dst_err <= '1';
680
 
681
            end if;
682
 
683
        end if;
684
      end if;
685
    end process;
686
 
687
 
688
 
689
 
690
    -- ----------------------------------------------
691
    -- Monitor State Machine
692
    -- ----------------------------------------------
693
 
694
    process( tx_clk_int, reset )
695
 
696
        variable hi,lo  : integer;
697
        variable cnttmp : integer range 0 to 65536;
698
        variable i      : integer;
699
        variable flen   : integer;
700
 
701
    begin
702
      if( reset = '1' ) then
703
 
704
            state      <= S_IDLE;
705
            last_state <= S_IDLE;
706
 
707
            count          <= 0;
708
            frame_err      <= '0';   -- state machine abort indicator
709
 
710
      elsif(tx_clk_int='1' and tx_clk_int'event ) then
711
 
712
          -- remember last state and increment internal counter
713
 
714
          last_state <= state;
715
 
716
          if(count < 65535) then
717
             cnttmp := count+1;
718
          else
719
             cnttmp := count ;
720
          end if;
721
 
722
 
723
          -- Abort detection: If enable goes low in middle of frame
724
 
725
          if( (state/=S_IDLE) and (state/=S_ABORT) and (state /= S_UTYPE) and tx_dv='0' ) then
726
 
727
              state     <= S_ABORT;
728
 
729
          else
730
 
731
            case state is
732
 
733
            when S_ABORT => if( tx_dv='1' ) then
734
 
735
                                if( last_tx_dv='0' and data_only='1' ) then  -- only 1 clock cycle inbetween
736
                                   if (ENABLE_SHIFT16 = 0) then
737
                                    state <= S_DST;
738
                                   else
739
                                                                        state <= S_Dword32Aligned;
740
                                   end if;
741
 
742
                                    cnttmp := 1;
743
                                    frame_err  <= '0';
744
 
745
                                else
746
 
747
                                    state <= S_ABORT;    -- wait til tx stops transmission
748
 
749
                                end if;
750
 
751
                            else
752
 
753
                                state <= S_IDLE;
754
 
755
                            end if;
756
 
757
                            frame_err <= '1';
758
 
759
 
760
            when S_IDLE  => if( tx_sof='1' ) then       -- we miss the very first !
761
                                cnttmp      := 1;       -- therefore need to count to 1 immediately
762
                                frame_err  <= '0';
763
 
764
                                if( data_only='1' ) then     -- no preamble checking ?
765
 
766
                                  if (ENABLE_SHIFT16 = 0) then
767
                                   state <= S_DST;
768
                                  else
769
                                   state <= S_Dword32Aligned;
770
                                  end if;
771
 
772
                                else
773
 
774
                                    state <= S_PRMBL;
775
 
776
                                end if;
777
 
778
                            else
779
 
780
                                cnttmp      := 0;  -- keep it to zero always 
781
 
782
                            end if;
783
 
784
 
785
            when S_PRMBL => if( txd=X"D5" ) then
786
 
787
                                state   <= S_DST;
788
                                cnttmp  := 0;
789
                            end if;
790
 
791
 
792
            when S_Dword32Aligned
793
                         => if( count = 1) then
794
 
795
                                state  <= S_DST;
796
                                cnttmp := 0;
797
                            end if;
798
 
799
            when S_DST   => if( count = 5) then
800
 
801
                                state  <= S_SRC;
802
                                cnttmp := 0;
803
                            end if;
804
 
805
 
806
            when S_SRC   => if( count = 5) then
807
 
808
                                state  <= S_TYPELEN;
809
                                cnttmp := 0;
810
                            end if;
811
 
812
 
813
          when S_TYPELEN => if( count/=0 ) then    -- second half of 2-octet field
814
 
815
                                cnttmp := 0;
816
 
817
                                flen := conv_integer('0' & ilen(15 downto 8) & txd );  -- need it NOW
818
 
819
                                if( (jumbo_en='1' and (flen <= 9000)) or (flen <= 1500)) then
820
 
821
                                    -- ok normal user frame. check if data or 0 length
822
 
823
                                    if( flen /= 0 ) then
824
 
825
                                        state <= S_DATA;
826
 
827
                                    else                     -- no data, PAD or finished
828
 
829
                                        if( data_only='1' ) then
830
 
831
                                            state <= S_IDLE; -- Ok, we are done dont expect anything more
832
 
833
                                        else
834
 
835
                                            state <= S_PAD;  -- zero-length frame needs padding
836
 
837
                                        end if;
838
 
839
                                    end if;
840
 
841
                                else -- not normal frame
842
 
843
                                    if( flen = 16#8808# ) then
844
 
845
                                        state <= S_PAUSE;
846
 
847
                                    elsif( flen = 16#8100# ) then
848
 
849
                                        state <= S_TAG;
850
 
851
                                    else
852
 
853
                                        state   <= S_UTYPE; -- S_ABORT;    -- unknown type
854
 
855
                                    end if;
856
                                end if;
857
                            end if;
858
 
859
 
860
            when S_PAUSE => if(   count>=3 ) then -- need to overread opcode
861
 
862
                                state <= S_PAD;
863
                                cnttmp := 0;
864
 
865
                            end if;
866
 
867
 
868
            when S_TAG  =>  if( count>=1 ) then
869
 
870
                                state <= S_LEN;
871
                                cnttmp := 0;
872
 
873
                            end if;
874
 
875
            when S_LEN  =>  if( count >= 1) then   -- Length after VLAN TAG
876
 
877
                                cnttmp := 0;
878
 
879
                                flen := conv_integer('0' & ilen(15 downto 8) & txd );  -- need it NOW
880
 
881
                                if ( flen = 16#8100# ) then
882
 
883
                                        state <= S_TAG;
884
 
885
                                elsif( flen /= 0 ) then
886
 
887
                                    state <= S_DATA;
888
 
889
                                else                     -- no data, PAD or finished
890
 
891
                                    if( data_only='1' ) then
892
 
893
                                        state <= S_IDLE; -- Ok, we are done dont expect CRC
894
 
895
                                    else
896
 
897
                                        state <= S_PAD;
898
 
899
                                    end if;
900
                                end if;
901
                            end if;
902
 
903
            when S_DATA  => if( count >= (conv_integer(ilen)-1)) then
904
 
905
                                cnttmp := 0;
906
 
907
                                if( data_only='1' ) then      -- no PAD and no CRC ?
908
 
909
                                    state <= S_IDLE;
910
 
911
                                elsif( poscnt < 60-1 ) then   -- expect padding ?
912
 
913
                                    state <= S_PAD;
914
 
915
                                else
916
 
917
                                    state <= S_CRC;
918
 
919
                                end if;
920
                             end if;
921
 
922
 
923
             when S_PAD    => if( poscnt >= (60-1) ) then
924
 
925
                                  state <= S_CRC;
926
                                  cnttmp := 0;
927
 
928
                              end if;
929
 
930
 
931
             when S_CRC    => if( count >= 3 ) then
932
 
933
                                  state <= S_IDLE;
934
                                  cnttmp := 0;
935
 
936
                              end if;
937
 
938
             when S_UTYPE  => if( tx_dv='0' ) then   -- unknown type... wait for end of frame
939
 
940
                                  state <= S_IDLE;
941
                                  cnttmp := 0;
942
 
943
 
944
                              end if;
945
 
946
             end case;
947
 
948
           end if;  -- abort                    
949
 
950
 
951
           -- load the counter with the new value                   
952
 
953
           count <= cnttmp;
954
 
955
 
956
      end if;
957
   end process;
958
 
959
end behave;
960
 
961
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.