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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [eth/] [core/] [greth_tx.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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