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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [ethlib/] [greth_tx.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003 - 2008, Gaisler Research
4
--  Copyright (C) 2008 - 2014, Aeroflex Gaisler
5
--  Copyright (C) 2015 - 2016, Cobham Gaisler
6
--
7
--  This program is free software; you can redistribute it and/or modify
8
--  it under the terms of the GNU General Public License as published by
9
--  the Free Software Foundation; either version 2 of the License, or
10
--  (at your option) any later version.
11
--
12
--  This program is distributed in the hope that it will be useful,
13
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
--  GNU General Public License for more details.
16
--
17
--  You should have received a copy of the GNU General Public License
18
--  along with this program; if not, write to the Free Software
19
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20
-----------------------------------------------------------------------------
21
-- Entity:      greth_tx
22
-- File:        greth_tx.vhd
23
-- Author:      Marko Isomaki 
24
-- Description: Ethernet transmitter
25
------------------------------------------------------------------------------
26
library ieee;
27
use ieee.std_logic_1164.all;
28
library commonlib;
29
use commonlib.types_common.all;
30
library ethlib;
31
use ethlib.types_eth.all;
32
 
33
entity greth_tx is
34
  generic(
35
    ifg_gap        : integer := 24;
36
    attempt_limit  : integer := 16;
37
    backoff_limit  : integer := 10;
38
    nsync          : integer range 1 to 2 := 2;
39
    rmii           : integer range 0 to 1  := 0;
40
    gmiimode       : integer range 0 to 1 := 0
41
    );
42
  port(
43
    rst            : in  std_ulogic;
44
    clk            : in  std_ulogic;
45
    txi            : in  host_tx_type;
46
    txo            : out tx_host_type
47
  );
48
end entity;
49
 
50
architecture rtl of greth_tx is
51
  function mirror2(din : in std_logic_vector(3 downto 0))
52
                        return std_logic_vector is
53
    variable do : std_logic_vector(3 downto 0);
54
  begin
55
    do(3) := din(0); do(2) := din(1);
56
    do(1) := din(2); do(0) := din(3);
57
    return do;
58
  end function;
59
 
60
  function init_ifg(
61
    ifg_gap : in integer;
62
    rmii    : in integer)
63
              return integer is
64
  begin
65
    if rmii = 0 then
66
      return log2(ifg_gap);
67
    else
68
      return log2(ifg_gap*20);
69
    end if;
70
  end function;
71
 
72
  constant maxattempts : std_logic_vector(4 downto 0) :=
73
    conv_std_logic_vector(attempt_limit, 5);
74
 
75
  --transmitter constants
76
  constant ifg_bits : integer := init_ifg(ifg_gap, rmii);
77
  constant ifg_p1 : std_logic_vector(ifg_bits-1 downto 0) :=
78
    conv_std_logic_vector((ifg_gap)/3, ifg_bits);
79
  constant ifg_p2 : std_logic_vector(ifg_bits-1 downto 0) :=
80
    conv_std_logic_vector((ifg_gap*2)/3, ifg_bits);
81
  constant ifg_p1_r100 : std_logic_vector(ifg_bits-1 downto 0) :=
82
    conv_std_logic_vector((ifg_gap*2)/3, ifg_bits);
83
  constant ifg_p2_r100 : std_logic_vector(ifg_bits-1 downto 0) :=
84
    conv_std_logic_vector(rmii*(ifg_gap*4)/3, ifg_bits);
85
  constant ifg_p1_r10 : std_logic_vector(ifg_bits-1 downto 0) :=
86
    conv_std_logic_vector(rmii*(ifg_gap*20)/3, ifg_bits);
87
  constant ifg_p2_r10 : std_logic_vector(ifg_bits-1 downto 0) :=
88
    conv_std_logic_vector(rmii*(ifg_gap*40)/3, ifg_bits);
89
 
90
  function ifg_sel(
91
    rmii  : in integer;
92
    p1    : in integer;
93
    speed : in std_ulogic)
94
            return std_logic_vector is
95
  begin
96
    if p1 = 1 then
97
      if rmii = 0 then
98
        return ifg_p1;
99
      else
100
        if speed = '1' then
101
          return ifg_p1_r100;
102
        else
103
          return ifg_p1_r10;
104
        end if;
105
      end if;
106
    else
107
      if rmii = 0 then
108
        return ifg_p2;
109
      else
110
        if speed = '1' then
111
          return ifg_p2_r100;
112
        else
113
          return ifg_p2_r10;
114
        end if;
115
      end if;
116
    end if;
117
  end function;
118
 
119
  --transmitter types
120
  type tx_state_type is (idle, preamble, sfd, data1, data2, pad1, pad2, fcs,
121
    fcs2, finish, calc_backoff, wait_backoff, send_jam, send_jam2,
122
    check_attempts);
123
  type def_state_type is (monitor, def_on, ifg1, ifg2, frame_waitingst);
124
 
125
  type tx_reg_type is record
126
    --deference process
127
    def_state        : def_state_type;
128
    ifg_cycls        : std_logic_vector(ifg_bits-1 downto 0);
129
    deferring        : std_ulogic;
130
    was_transmitting : std_ulogic;
131
 
132
    --tx process
133
    main_state   : tx_state_type;
134
    transmitting : std_ulogic;
135
    tx_en        : std_ulogic;
136
    txd          : std_logic_vector(3 downto 0);
137
    cnt          : std_logic_vector(3 downto 0);
138
    icnt         : std_logic_vector(1 downto 0);
139
    crc          : std_logic_vector(31 downto 0);
140
    crc_en       : std_ulogic;
141
    byte_count   : std_logic_vector(10 downto 0);
142
    slot_count   : std_logic_vector(6 downto 0);
143
    random       : std_logic_vector(9 downto 0);
144
    delay_val    : std_logic_vector(9 downto 0);
145
    retry_cnt    : std_logic_vector(4 downto 0);
146
    status       : std_logic_vector(1 downto 0);
147
    data         : std_logic_vector(31 downto 0);
148
 
149
    --synchronization
150
    read         : std_ulogic;
151
    done         : std_ulogic;
152
    restart      : std_ulogic;
153
    start        : std_logic_vector(nsync downto 0);
154
    read_ack     : std_logic_vector(nsync-1 downto 0);
155
    crs          : std_logic_vector(1 downto 0);
156
    col          : std_logic_vector(1 downto 0);
157
    fullduplex   : std_logic_vector(1 downto 0);
158
 
159
    --rmii
160
    crs_act      : std_ulogic;
161
    crs_prev     : std_ulogic;
162
    speed        : std_logic_vector(1 downto 0);
163
    rcnt         : std_logic_vector(3 downto 0);
164
    switch       : std_ulogic;
165
    txd_msb      : std_logic_vector(1 downto 0);
166
    zero         : std_ulogic;
167
    rmii_crc_en  : std_ulogic;
168
  end record;
169
 
170
  --transmitter signals
171
  signal r, rin  : tx_reg_type;
172
  signal txrst   : std_ulogic;
173
  signal vcc     : std_ulogic;
174
 
175
begin
176
  vcc <= '1';
177
 
178
  tx_rst : eth_rstgen
179
  port map(rst, clk, vcc, txrst, open);
180
 
181
  tx : process(txrst, r, txi) is
182
    variable collision     : std_ulogic;
183
    variable frame_waiting : std_ulogic;
184
    variable index         : integer range 0 to 7;
185
    variable start         : std_ulogic;
186
    variable read_ack      : std_ulogic;
187
    variable v             : tx_reg_type;
188
 
189
    variable crs           : std_ulogic;
190
    variable col           : std_ulogic;
191
    variable tx_done       : std_ulogic;
192
  begin
193
    v := r; frame_waiting := '0'; tx_done := '0'; v.rmii_crc_en := '0';
194
 
195
    --synchronization
196
    v.col(1) := r.col(0); v.col(0) := txi.rx_col;
197
    v.crs(1) := r.crs(0); v.crs(0) := txi.rx_crs;
198
    v.fullduplex(0) := txi.full_duplex;
199
    v.fullduplex(1) := r.fullduplex(0);
200
 
201
    v.start(0)       := txi.start;
202
    v.read_ack(0)    := txi.readack;
203
 
204
    if nsync = 2 then
205
      v.start(1)       := r.start(0);
206
      v.read_ack(1)    := r.read_ack(0);
207
    end if;
208
 
209
    start       := r.start(nsync) xor r.start(nsync-1);
210
    read_ack    := not (r.read    xor r.read_ack(nsync-1));
211
 
212
    --crc generation
213
    if (r.crc_en = '1') and ((rmii = 0) or (r.rmii_crc_en = '1')) then
214
      v.crc := calccrc(r.txd, r.crc);
215
    end if;
216
 
217
    --rmii
218
    if rmii = 0 then
219
      col := r.col(1); crs := r.crs(1);
220
      tx_done := '1';
221
    else
222
      v.crs_prev := r.crs(1);
223
      if (r.crs(0) and not r.crs_act) = '1' then
224
        v.crs_act := '1';
225
      end if;
226
      if (r.crs(1) or r.crs(0)) = '0' then
227
        v.crs_act := '0';
228
      end if;
229
      crs := r.crs(1) and not ((not r.crs_prev) and r.crs_act);
230
      col := crs and r.tx_en;
231
 
232
      v.speed(1) := r.speed(0); v.speed(0) := txi.speed;
233
 
234
      if r.tx_en = '1' then
235
        v.rcnt := r.rcnt - 1;
236
        if r.speed(1) = '1' then
237
          v.switch := not r.switch;
238
          if r.switch = '1' then
239
            tx_done := '1'; v.rmii_crc_en := '1';
240
          end if;
241
          if r.switch = '0' then
242
            v.txd(1 downto 0) := r.txd_msb;
243
          end if;
244
        else
245
          v.zero := '0';
246
          if r.rcnt = "0001" then
247
            v.zero := '1';
248
          end if;
249
          if r.zero = '1' then
250
            v.switch := not r.switch;
251
            v.rcnt := "1001";
252
            if r.switch = '0' then
253
              v.txd(1 downto 0) := r.txd_msb;
254
            end if;
255
          end if;
256
          if (r.switch and r.zero) = '1' then
257
            tx_done := '1'; v.rmii_crc_en := '1';
258
          end if;
259
        end if;
260
      end if;
261
    end if;
262
 
263
    collision := col and not r.fullduplex(1);
264
 
265
    --main fsm
266
    case r.main_state is
267
    when idle =>
268
      v.transmitting := '0';
269
      if rmii = 1 then
270
        v.rcnt := "1001"; v.switch := '0';
271
      end if;
272
      if (start and not r.deferring) = '1' then
273
        v.main_state := preamble; v.transmitting := '1'; v.tx_en := '1';
274
        v.byte_count := (others => '1'); v.status := (others => '0');
275
        v.read := not r.read; v.start(nsync) := r.start(nsync-1);
276
      elsif start = '1' then
277
        frame_waiting := '1';
278
      end if;
279
      v.txd := "0101"; v.cnt := "1110";
280
    when preamble =>
281
      if tx_done = '1' then
282
        v.cnt := r.cnt - 1;
283
        if r.cnt = "0000" then
284
          v.txd := "1101"; v.main_state := sfd;
285
        end if;
286
        if collision = '1' then v.main_state := send_jam; end if;
287
      end if;
288
    when sfd =>
289
      if tx_done = '1' then
290
        v.main_state := data1; v.icnt := (others => '0'); v.crc_en := '1';
291
        v.crc := (others => '1'); v.byte_count := (others => '0');
292
        v.txd := txi.data(27 downto 24);
293
        if (read_ack and txi.valid) = '0' then
294
          v.status(0) := '1'; v.main_state := finish; v.tx_en := '0';
295
        else
296
          v.data := txi.data; v.read := not r.read;
297
        end if;
298
        if collision = '1' then v.main_state := send_jam; end if;
299
      end if;
300
    when data1 =>
301
      index := conv_integer(r.icnt);
302
      if tx_done = '1' then
303
        v.byte_count := r.byte_count + 1;
304
        v.main_state := data2; v.icnt := r.icnt + 1;
305
        case index is
306
        when 0 => v.txd := r.data(31 downto 28);
307
        when 1 => v.txd := r.data(23 downto 20);
308
        when 2 => v.txd := r.data(15 downto 12);
309
        when 3 => v.txd := r.data(7 downto 4);
310
        when others => null;
311
        end case;
312
        if v.byte_count = txi.len then
313
          v.tx_en := '1';
314
          if conv_integer(v.byte_count) >= 60 then
315
            v.main_state := fcs; v.cnt := (others => '0');
316
          else
317
            v.main_state := pad1;
318
          end if;
319
        elsif index = 3 then
320
          if (read_ack and txi.valid) = '0' then
321
            v.status(0) := '1'; v.main_state := finish; v.tx_en := '0';
322
          else
323
            v.data := txi.data; v.read := not r.read;
324
          end if;
325
        end if;
326
        if collision = '1' then v.main_state := send_jam; end if;
327
      end if;
328
    when data2 =>
329
      index := conv_integer(r.icnt);
330
      if tx_done = '1' then
331
        v.main_state := data1;
332
        case index is
333
        when 0 => v.txd := r.data(27 downto 24);
334
        when 1 => v.txd := r.data(19 downto 16);
335
        when 2 => v.txd := r.data(11 downto 8);
336
        when 3 => v.txd := r.data(3 downto 0);
337
        when others => null;
338
        end case;
339
        if collision = '1' then v.main_state := send_jam; end if;
340
      end if;
341
    when pad1 =>
342
      if tx_done = '1' then
343
        v.main_state := pad2;
344
        if collision = '1' then v.main_state := send_jam; end if;
345
      end if;
346
    when pad2 =>
347
      if tx_done = '1' then
348
        v.byte_count := r.byte_count + 1;
349
        if conv_integer(v.byte_count) = 60 then
350
          v.main_state := fcs; v.cnt := (others => '0');
351
        else
352
          v.main_state := pad1;
353
        end if;
354
        if collision = '1' then v.main_state := send_jam; end if;
355
      end if;
356
    when fcs =>
357
      if tx_done = '1' then
358
        v.cnt := r.cnt + 1; v.crc_en := '0'; index := conv_integer(r.cnt);
359
        case index is
360
        when 0 => v.txd := mirror2(not v.crc(31 downto 28));
361
        when 1 => v.txd := mirror2(not r.crc(27 downto 24));
362
        when 2 => v.txd := mirror2(not r.crc(23 downto 20));
363
        when 3 => v.txd := mirror2(not r.crc(19 downto 16));
364
        when 4 => v.txd := mirror2(not r.crc(15 downto 12));
365
        when 5 => v.txd := mirror2(not r.crc(11 downto 8));
366
        when 6 => v.txd := mirror2(not r.crc(7 downto 4));
367
        when 7 => v.txd := mirror2(not r.crc(3 downto 0));
368
                  v.main_state := fcs2;
369
        when others => null;
370
        end case;
371
      end if;
372
    when fcs2 =>
373
      if tx_done = '1' then
374
        v.main_state := finish; v.tx_en := '0';
375
      end if;
376
    when finish =>
377
      v.tx_en := '0'; v.transmitting := '0'; v.main_state := idle;
378
      v.retry_cnt := (others => '0'); v.done := not r.done;
379
    when send_jam =>
380
      if tx_done = '1' then
381
        v.cnt := "0110"; v.main_state := send_jam2; v.crc_en := '0';
382
      end if;
383
    when send_jam2 =>
384
      if tx_done = '1' then
385
        v.cnt := r.cnt - 1;
386
        if r.cnt = "0000" then
387
          v.main_state := check_attempts; v.retry_cnt := r.retry_cnt + 1;
388
          v.tx_en := '0';
389
        end if;
390
      end if;
391
    when check_attempts =>
392
      v.transmitting := '0';
393
      if r.retry_cnt = maxattempts then
394
        v.main_state := finish; v.status(1) := '1';
395
      else
396
        v.main_state := calc_backoff; v.restart := not r.restart;
397
      end if;
398
      v.tx_en := '0';
399
    when calc_backoff =>
400
      v.delay_val := (others => '0');
401
      for i in 1 to backoff_limit-1 loop
402
        if i < conv_integer(r.retry_cnt)+1 then
403
          v.delay_val(i) := r.random(i);
404
        end if;
405
      end loop;
406
      v.main_state := wait_backoff; v.slot_count := (others => '1');
407
    when wait_backoff =>
408
      if conv_integer(r.delay_val) = 0 then
409
        v.main_state := idle;
410
      end if;
411
      v.slot_count := r.slot_count - 1;
412
      if conv_integer(r.slot_count) = 0 then
413
        v.slot_count := (others => '1'); v.delay_val := r.delay_val - 1;
414
      end if;
415
    when others =>
416
      v.main_state := idle;
417
    end case;
418
 
419
    --random values; 
420
    v.random := r.random(8 downto 0) & (not (r.random(2) xor r.random(9)));
421
 
422
    --deference
423
    case r.def_state is
424
    when monitor =>
425
      v.was_transmitting := '0';
426
      if ( (crs and not r.fullduplex(1)) or
427
           (r.transmitting and r.fullduplex(1)) ) = '1' then
428
        v.deferring := '1'; v.def_state := def_on;
429
        v.was_transmitting := r.transmitting;
430
      end if;
431
    when def_on =>
432
      v.was_transmitting := r.was_transmitting or r.transmitting;
433
      if r.fullduplex(1) = '1' then
434
        if r.transmitting = '0' then v.def_state := ifg1; end if;
435
        v.ifg_cycls := ifg_sel(rmii, 1, r.speed(1));
436
      else
437
        if (r.transmitting or crs) = '0' then
438
          v.def_state := ifg1; v.ifg_cycls := ifg_sel(rmii, 1, r.speed(1));
439
        end if;
440
      end if;
441
    when ifg1 =>
442
      v.ifg_cycls := r.ifg_cycls - 1;
443
      if r.ifg_cycls = zero32(ifg_bits-1 downto 0) then
444
        v.def_state := ifg2;
445
        v.ifg_cycls := ifg_sel(rmii, 0, r.speed(1));
446
      elsif (crs and not r.fullduplex(1)) = '1' then
447
        v.ifg_cycls := ifg_sel(rmii, 1, r.speed(1));
448
      end if;
449
    when ifg2 =>
450
      v.ifg_cycls := r.ifg_cycls - 1;
451
      if r.ifg_cycls = zero32(ifg_bits-1 downto 0) then
452
        v.deferring := '0';
453
        if (r.fullduplex(1) or not frame_waiting) = '1' then
454
          v.def_state := monitor;
455
        elsif frame_waiting = '1' then
456
          v.def_state := frame_waitingst;
457
        end if;
458
      end if;
459
    when frame_waitingst =>
460
       if frame_waiting = '0' then v.def_state := monitor; end if;
461
    when others => v.def_state := monitor;
462
    end case;
463
 
464
    if rmii = 1 then
465
      v.txd_msb := v.txd(3 downto 2);
466
    end if;
467
 
468
    if txrst = '0' then
469
      v.main_state := idle; v.random := (others => '0');
470
      v.def_state := monitor; v.deferring := '0'; v.tx_en := '0';
471
      v.done := '0'; v.restart := '0'; v.read := '0';
472
      v.start := (others => '0'); v.read_ack := (others => '0');
473
      v.icnt := (others => '0'); v.delay_val := (others => '0');
474
      v.ifg_cycls := (others => '0');
475
      v.crs_act := '0';
476
      v.slot_count := (others => '1');
477
      v.retry_cnt := (others => '0');
478
      v.cnt := (others => '0');
479
    end if;
480
 
481
    rin                      <= v;
482
    txo.tx_er                <= '0';
483
    txo.tx_en                <= r.tx_en;
484
    txo.txd                  <= r.txd;
485
    txo.done                 <= r.done;
486
    txo.read                 <= r.read;
487
    txo.restart              <= r.restart;
488
    txo.status               <= r.status;
489
  end process;
490
 
491
 
492
  gmiimode0 : if gmiimode = 0 generate
493
    txregs0 : process(clk) is
494
    begin
495
      if rising_edge(clk) then
496
        r <= rin;
497
        if txrst = '0' then
498
          r.icnt <= (others => '0'); r.delay_val <= (others => '0');
499
          r.cnt <= (others => '0');
500
        else
501
          r.icnt <= rin.icnt; r.delay_val <= rin.delay_val;
502
          r.cnt <= rin.cnt;
503
        end if;
504
      end if;
505
    end process;
506
  end generate;
507
 
508
  gmiimode1 : if gmiimode = 1 generate
509
    txregs0 : process(clk) is
510
    begin
511
      if rising_edge(clk) then
512
        if (txi.datavalid = '1' or txrst = '0')  then r <= rin; end if;
513
        if txrst = '0' then
514
          r.icnt <= (others => '0'); r.delay_val <= (others => '0');
515
          r.cnt <= (others => '0');
516
        else
517
          if txi.datavalid = '1' then
518
            r.icnt <= rin.icnt; r.delay_val <= rin.delay_val;
519
            r.cnt <= rin.cnt;
520
          end if;
521
        end if;
522
      end if;
523
    end process;
524
  end generate;
525
 
526
end architecture;
527
 

powered by: WebSVN 2.1.0

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