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

powered by: WebSVN 2.1.0

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