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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [ethlib/] [greth_rx.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_rx 
22
-- File:        greth_rx.vhd
23
-- Author:      Marko Isomaki 
24
-- Description: Ethernet receiver
25
------------------------------------------------------------------------------
26
library ieee;
27
use ieee.std_logic_1164.all;
28
use ieee.numeric_std.all;
29
library commonlib;
30
use commonlib.types_common.all;
31
library ethlib;
32
use ethlib.types_eth.all;
33
 
34
entity greth_rx is
35
  generic(
36
    nsync          : integer range 1 to 2 := 2;
37
    rmii           : integer range 0 to 1 := 0;
38
    multicast      : integer range 0 to 1 := 0;
39
    maxsize        : integer := 1500;
40
    gmiimode       : integer range 0 to 1 := 0
41
    );
42
  port(
43
    rst            : in  std_ulogic;
44
    clk            : in  std_ulogic;
45
    rxi            : in  host_rx_type;
46
    rxo            : out rx_host_type
47
  );
48
end entity;
49
 
50
architecture rtl of greth_rx is
51
--  constant maxsize   : integer := 1518;
52
  constant maxsizerx : unsigned(15 downto 0) :=
53
    to_unsigned(maxsize + 18, 16);
54
  constant minsize   : integer := 64;
55
 
56
  --receiver types
57
  type rx_state_type is (idle, wait_sfd, data1, data2, errorst, report_status,
58
                         wait_report, check_crc, discard_packet);
59
 
60
  type rx_reg_type is record
61
    er              : std_ulogic;
62
    en              : std_ulogic;
63
    rxd             : std_logic_vector(3 downto 0);
64
    rxdp            : std_logic_vector(3 downto 0);
65
    crc             : std_logic_vector(31 downto 0);
66
    sync_start      : std_ulogic;
67
    gotframe        : std_ulogic;
68
    start           : std_ulogic;
69
    write           : std_ulogic;
70
    done            : std_ulogic;
71
    odd_nibble      : std_ulogic;
72
    lentype         : std_logic_vector(15 downto 0);
73
    ltfound         : std_ulogic;
74
    byte_count      : std_logic_vector(10 downto 0);
75
    data            : std_logic_vector(31 downto 0);
76
    dataout         : std_logic_vector(31 downto 0);
77
    rx_state        : rx_state_type;
78
    status          : std_logic_vector(3 downto 0);
79
    write_ack       : std_logic_vector(nsync-1 downto 0);
80
    done_ack        : std_logic_vector(nsync downto 0);
81
    rxen            : std_logic_vector(1 downto 0);
82
    got4b           : std_ulogic;
83
    mcasthash       : std_logic_vector(5 downto 0);
84
    hashlock        : std_ulogic;
85
 
86
    --rmii
87
    enold           : std_ulogic;
88
    act             : std_ulogic;
89
    dv              : std_ulogic;
90
    cnt             : std_logic_vector(3 downto 0);
91
    rxd2            : std_logic_vector(1 downto 0);
92
    speed           : std_logic_vector(1 downto 0);
93
    zero            : std_ulogic;
94
  end record;
95
 
96
  --receiver signals
97
  signal r, rin     : rx_reg_type;
98
  signal rxrst      : std_ulogic;
99
  signal vcc        : std_ulogic;
100
 
101
 
102
begin
103
  vcc <= '1';
104
 
105
  rx_rst : eth_rstgen
106
  port map(rst, clk, vcc, rxrst, open);
107
 
108
  rx : process(rxrst, r, rxi) is
109
    variable v         : rx_reg_type;
110
    variable index     : integer range 0 to 3;
111
    variable crc_en    : std_ulogic;
112
    variable write_req : std_ulogic;
113
    variable write_ack : std_ulogic;
114
    variable done_ack  : std_ulogic;
115
 
116
    variable er        : std_ulogic;
117
    variable dv        : std_ulogic;
118
    variable act       : std_ulogic;
119
    variable rxd       : std_logic_vector(3 downto 0);
120
  begin
121
    v := r; v.rxd := rxi.rxd(3 downto 0);
122
    if rmii = 0 then
123
      v.en := rxi.rx_dv;
124
    else
125
      v.en := rxi.rx_crs;
126
    end if;
127
    v.er := rxi.rx_er; write_req := '0'; crc_en := '0';
128
    index := conv_integer(r.byte_count(1 downto 0));
129
 
130
    --synchronization
131
    v.rxen(1) := r.rxen(0); v.rxen(0) := rxi.enable;
132
 
133
    v.write_ack(0) := rxi.writeack;
134
    v.done_ack(0)  := rxi.doneack;
135
 
136
    if nsync = 2 then
137
      v.write_ack(1) := r.write_ack(0);
138
      v.done_ack(1)  := r.done_ack(0);
139
    end if;
140
 
141
    write_ack := not (r.write xor r.write_ack(nsync-1));
142
    done_ack  := not (r.done xor r.done_ack(nsync-1));
143
 
144
    --rmii/mii
145
    if rmii = 0 then
146
      er := r.er; dv := r.en; act := r.en; rxd := r.rxd;
147
    else
148
      --sync 
149
      v.speed(1) := r.speed(0); v.speed(0) := rxi.speed;
150
 
151
      rxd := r.rxd(1 downto 0) & r.rxd2;
152
 
153
      if r.cnt = "0000" then
154
        v.cnt := "1001";
155
      else
156
        v.cnt := r.cnt - 1;
157
      end if;
158
 
159
      if v.cnt = "0000" then
160
        v.zero := '1';
161
      else
162
        v.zero := '0';
163
      end if;
164
 
165
      act := r.act; er := '0';
166
 
167
      if r.speed(1) = '0' then
168
        if r.zero = '1' then
169
          v.enold := r.en;
170
          dv := r.en and r.dv;
171
          v.dv := r.act and not r.dv;
172
          if r.dv = '0' then
173
            v.rxd2 := r.rxd(1 downto 0);
174
          end if;
175
          if (r.enold or r.en) = '0' then
176
            v.act := '0';
177
          end if;
178
        else
179
          dv := '0';
180
        end if;
181
      else
182
        v.enold := r.en;
183
        dv := r.en and r.dv;
184
        v.dv := r.act and not r.dv;
185
        v.rxd2 := r.rxd(1 downto 0);
186
        if (r.enold or r.en) = '0' then
187
          v.act := '0';
188
        end if;
189
      end if;
190
    end if;
191
 
192
    if (r.en and not r.act) = '1' then
193
      if (rxd = "0101") and (r.speed(1) or
194
         (not r.speed(1) and r.zero)) = '1' then
195
        v.act := '1'; v.dv := '0'; v.rxdp := rxd;
196
      end if;
197
    end if;
198
 
199
    if (dv = '1') then
200
      v.rxdp := rxd;
201
    end if;
202
 
203
    if multicast = 1 then
204
      if (r.byte_count(2 downto 0) = "110") and (r.hashlock = '0') then
205
        v.mcasthash := r.crc(5 downto 0); v.hashlock := '1';
206
      end if;
207
    end if;
208
 
209
    --fsm
210
    case r.rx_state is
211
    when idle =>
212
      v.gotframe := '0'; v.status := (others => '0'); v.got4b := '0';
213
      v.byte_count := (others => '0'); v.odd_nibble := '0';
214
      v.ltfound := '0';
215
      if multicast = 1 then
216
        v.hashlock := '0';
217
      end if;
218
      if (dv and r.rxen(1)) = '1' then
219
        if (rxd = "1101") and (r.rxdp = "0101") then
220
          v.rx_state := data1; v.sync_start := not r.sync_start;
221
        end if;
222
        v.start := '0'; v.crc := (others => '1');
223
        if er = '1' then v.status(2) := '1'; end if;
224
      elsif dv = '1' then
225
        v.rx_state := discard_packet;
226
      end if;
227
    when discard_packet =>
228
      if act = '0' then v.rx_state := idle; end if;
229
    when data1 =>
230
      if (act and dv) = '1' then
231
        crc_en := '1';
232
        v.odd_nibble := not r.odd_nibble; v.rx_state := data2;
233
        case index is
234
        when 0 => v.data(27 downto 24) := rxd;
235
        when 1 => v.data(19 downto 16) := rxd;
236
        when 2 => v.data(11 downto 8)  := rxd;
237
        when 3 => v.data(3 downto 0)   := rxd;
238
        end case;
239
      elsif act = '0' then
240
        v.rx_state := check_crc;
241
      end if;
242
      if (r.byte_count(1 downto 0) = "00" and (r.start and act and dv) = '1') then
243
        write_req := '1';
244
      end if;
245
      if er = '1' then v.status(2) := '1'; end if;
246
      if conv_integer(r.byte_count) > maxsizerx then
247
        v.rx_state := errorst; v.status(1) := '1';
248
        v.byte_count := r.byte_count - 4;
249
      end if;
250
      v.got4b := v.byte_count(2) or r.got4b;
251
    when data2 =>
252
      if (act and dv) = '1' then
253
        crc_en := '1';
254
        v.odd_nibble := not r.odd_nibble; v.rx_state := data1;
255
        v.byte_count := r.byte_count + 1; v.start := '1';
256
        case index is
257
        when 0 => v.data(31 downto 28) := rxd;
258
        when 1 => v.data(23 downto 20) := rxd;
259
        when 2 => v.data(15 downto 12) := rxd;
260
        when 3 => v.data(7 downto 4)   := rxd;
261
        end case;
262
      elsif act = '0' then
263
        v.rx_state := check_crc;
264
      end if;
265
      if er = '1' then v.status(2) := '1'; end if;
266
      v.got4b := v.byte_count(2) or r.got4b;
267
    when check_crc =>
268
      if r.crc /= X"C704DD7B" then
269
        if r.odd_nibble = '1' then v.status(0) := '1';
270
        else v.status(2) := '1'; end if;
271
      end if;
272
      if write_ack = '1' then
273
        if r.got4b = '1' then
274
          v.byte_count := r.byte_count - 4;
275
        else
276
          v.byte_count := (others => '0');
277
        end if;
278
        v.rx_state := report_status;
279
        if conv_integer(r.byte_count) < minsize then
280
          v.rx_state := wait_report; v.done := not r.done;
281
        end if;
282
      end if;
283
    when errorst =>
284
      if act = '0' then
285
        v.rx_state := wait_report; v.done := not r.done;
286
        v.gotframe := '1';
287
      end if;
288
    when report_status =>
289
      v.done := not r.done; v.rx_state := wait_report;
290
      v.gotframe := '1';
291
    when wait_report =>
292
      if done_ack = '1' then
293
        if act = '1' then
294
          v.rx_state := discard_packet;
295
        else
296
          v.rx_state := idle;
297
        end if;
298
      end if;
299
    when others => null;
300
    end case;
301
 
302
    --write to fifo
303
    if write_req = '1' then
304
      if (r.status(3) or not write_ack) = '1' then
305
        v.status(3) := '1';
306
      else
307
        v.dataout := r.data; v.write := not r.write;
308
      end if;
309
      if (r.byte_count(4 downto 2) = "100") and (r.ltfound = '0') then
310
        v.lentype := r.data(31 downto 16) + 14; v.ltfound := '1';
311
      end if;
312
    end if;
313
 
314
    if write_ack = '1' then
315
      if rxi.writeok = '0' then v.status(3) := '1'; end if;
316
    end if;
317
 
318
    --crc generation
319
    if crc_en = '1' then
320
      v.crc := calccrc(rxd, r.crc);
321
    end if;
322
 
323
    if rxrst = '0' then
324
      v.rx_state  := idle; v.write := '0'; v.done := '0'; v.sync_start := '0';
325
      v.done_ack  := (others => '0');
326
      v.gotframe  := '0'; v.write_ack := (others => '0');
327
      v.dv := '0'; v.cnt := (others => '0'); v.zero := '0';
328
      v.byte_count := (others => '0'); v.lentype := (others => '0');
329
      v.status := (others => '0'); v.got4b := '0'; v.odd_nibble := '0';
330
      v.ltfound := '0';
331
      v.mcasthash := (others => '0');
332
      v.dataout := (others => '0');
333
      if multicast = 1 then
334
        v.hashlock := '0';
335
      end if;
336
 
337
    end if;
338
    if rmii = 0 then
339
        v.cnt := (others => '0'); v.zero := '0';
340
    end if;
341
 
342
    rin            <= v;
343
    rxo.dataout    <= r.dataout;
344
    rxo.start      <= r.sync_start;
345
    rxo.done       <= r.done;
346
    rxo.write      <= r.write;
347
    rxo.status     <= r.status;
348
    rxo.gotframe   <= r.gotframe;
349
    rxo.byte_count <= r.byte_count;
350
    rxo.lentype    <= r.lentype;
351
    rxo.mcasthash  <= r.mcasthash;
352
 
353
  end process;
354
 
355
  gmiimode0 : if gmiimode = 0 generate
356
     rxregs0 : process(clk) is
357
     begin
358
       if rising_edge(clk) then
359
         r <= rin;
360
       end if;
361
     end process;
362
  end generate;
363
 
364
  gmiimode1 : if gmiimode = 1 generate
365
     rxregs1 : process(clk) is
366
     begin
367
       if rising_edge(clk) then
368
         if (rxi.rx_en = '1' or rxrst = '0') then r <= rin; end if;
369
       end if;
370
     end process;
371
  end generate;
372
 
373
 
374
end architecture;
375
 

powered by: WebSVN 2.1.0

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