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

Subversion Repositories fade_ether_protocol

[/] [fade_ether_protocol/] [trunk/] [stable_jumbo_frames_version/] [fpga/] [src/] [eth_receiver64.vhd] - Blame information for rev 44

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 wzab
-------------------------------------------------------------------------------
2
-- Title      : FPGA Ethernet interface - block receiving packets from MII PHY
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : eth_receiver4.vhd
6
-- Author     : Wojciech M. Zabolotny (wzab@ise.pw.edu.pl)
7
-- License    : BSD License
8
-- Company    : 
9
-- Created    : 2012-03-30
10 18 wzab
-- Last update: 2014-10-12
11 15 wzab
-- Platform   : 
12
-- Standard   : VHDL'93
13
-------------------------------------------------------------------------------
14 18 wzab
-- Description: This file implements the state machine, responsible for
15
-- reception of packets and passing them to the acknowledgements and commands
16
-- FIFO
17 15 wzab
-------------------------------------------------------------------------------
18
-- Copyright (c) 2012 
19
-------------------------------------------------------------------------------
20
-- Revisions  :
21
-- Date        Version  Author  Description
22
-- 2012-03-30  1.0      WZab      Created
23
-------------------------------------------------------------------------------
24
 
25
-- Uwaga! Tu mamy rzeczywiste problemy z obsluga odebranych pakietow!
26
-- 
27
 
28
library ieee;
29
use ieee.std_logic_1164.all;
30
use ieee.numeric_std.all;
31
library work;
32 18 wzab
use work.desc_mgr_pkg.all;
33 15 wzab
use work.pkt_ack_pkg.all;
34
use work.pkg_newcrc32_d64.all;
35
use work.pkg_newcrc32_d32.all;
36
use work.pkg_newcrc32_d16.all;
37
 
38
 
39
entity eth_receiver is
40
 
41
  port (
42
    -- Configuration
43
    peer_mac       : out std_logic_vector(47 downto 0);
44
    my_mac         : in  std_logic_vector(47 downto 0);
45
    my_ether_type  : in  std_logic_vector(15 downto 0);
46
    transmit_data  : out std_logic;
47
    restart        : out std_logic;
48
    -- ACK FIFO interface
49
    ack_fifo_full  : in  std_logic;
50
    ack_fifo_wr_en : out std_logic;
51
    ack_fifo_din   : out std_logic_vector(pkt_ack_width-1 downto 0);
52
    -- System interface
53
    clk            : in  std_logic;
54
    rst_n          : in  std_logic;
55
    dbg            : out std_logic_vector(3 downto 0);
56
    cmd            : out std_logic_vector(31 downto 0);
57
    arg            : out std_logic_vector(31 downto 0);
58
    crc            : out std_logic_vector(31 downto 0);
59
    -- MAC interface
60
    Rx_Clk         : in  std_logic;
61
    RxC            : in  std_logic_vector(7 downto 0);
62
    RxD            : in  std_logic_vector(63 downto 0)
63
    );
64
 
65
end eth_receiver;
66
 
67
 
68
architecture beh1 of eth_receiver is
69
 
70
  type T_STATE is (ST_RCV_IDLE, ST_RCV_PREAMB, ST_CHECK_PREAMB,
71
                   ST_RCV_HEADER1, ST_RCV_HEADER2, ST_RCV_CMD,
72
                   ST_RCV_WAIT_IDLE, ST_RCV_ARGS, ST_RCV_PROCESS, ST_RCV_UPDATE,
73
                   ST_RCV_TRAILER);
74
 
75
 
76
 
77
  function rev(a : in std_logic_vector)
78
    return std_logic_vector is
79
    variable result : std_logic_vector(a'range);
80
    alias aa        : std_logic_vector(a'reverse_range) is a;
81
  begin
82
    for i in aa'range loop
83
      result(i) := aa(i);
84
    end loop;
85
    return result;
86
  end;  -- function reverse_any_bus
87
 
88
  constant C_PROTO_ID : std_logic_vector(31 downto 0) := x"fade0100";
89
 
90
  type T_RCV_REGS is record
91
    state         : T_STATE;
92
    swap_lanes    : std_logic;
93
    transmit_data : std_logic;
94
    restart       : std_logic;
95
    update_flag   : std_logic;
96
    count         : integer;
97
    dbg           : std_logic_vector(3 downto 0);
98
    crc32         : std_logic_vector(31 downto 0);
99
    cmd           : std_logic_vector(31 downto 0);
100
    arg           : std_logic_vector(31 downto 0);
101
    mac_addr      : std_logic_vector(47 downto 0);
102
    peer_mac      : std_logic_vector(47 downto 0);
103
  end record;
104
 
105
  constant RCV_REGS_INI : T_RCV_REGS := (
106
    state         => ST_RCV_IDLE,
107
    swap_lanes    => '0',
108
    transmit_data => '0',
109
    restart       => '0',
110
    update_flag   => '0',
111
    count         => 0,
112
    dbg           => (others => '0'),
113
    crc32         => (others => '0'),
114
    cmd           => (others => '0'),
115
    arg           => (others => '0'),
116
    mac_addr      => (others => '0'),
117
    peer_mac      => (others => '0')
118
    );
119
 
120
  signal r, r_n : T_RCV_REGS := RCV_REGS_INI;
121
 
122
  type T_RCV_COMB is record
123
    ack_fifo_wr_en : std_logic;
124
    Rx_mac_rd      : std_logic;
125
    ack_fifo_din   : std_logic_vector(pkt_ack_width-1 downto 0);
126
    restart        : std_logic;
127
  end record;
128
 
129
  constant RCV_COMB_DEFAULT : T_RCV_COMB := (
130
    ack_fifo_wr_en => '0',
131
    Rx_mac_rd      => '0',
132
    ack_fifo_din   => (others => '0'),
133
    restart        => '0'
134
    );
135
 
136
  signal c : T_RCV_COMB := RCV_COMB_DEFAULT;
137
 
138
  signal rxd_sw, rxd_del : std_logic_vector(63 downto 0);
139
  signal rxc_sw, rxc_del : std_logic_vector(7 downto 0);
140
 
141
  signal rx_rst_n, rx_rst_n_0, rx_rst_n_1          : std_logic := '0';
142
  signal update_flag_0, update_flag_1, update_flag : std_logic := '0';
143
 
144
begin  -- beh1
145
 
146
  ack_fifo_din   <= c.ack_fifo_din;
147
  ack_fifo_wr_en <= c.ack_fifo_wr_en;
148
 
149
  --dbg <= r.dbg;
150
  crc <= r.crc32;
151
  cmd <= r.cmd;
152
  arg <= r.arg;
153
  -- Lane switcher processes
154
  lsw_c1 : process (RxC, RxC(3 downto 0), RxC_del(7 downto 4), RxD,
155
                    RxD(31 downto 0), RxD_del(63 downto 32), r.swap_lanes) is
156
  begin  -- process lsw_c1
157
    if r.swap_lanes = '1' then
158
      RxD_Sw(63 downto 32) <= RxD(31 downto 0);
159
      RxD_Sw(31 downto 0)  <= RxD_del(63 downto 32);
160
      RxC_Sw(7 downto 4)   <= RxC(3 downto 0);
161
      RxC_Sw(3 downto 0)   <= RxC_del(7 downto 4);
162
    else
163
      RxD_Sw <= RxD;
164
      RxC_Sw <= RxC;
165
    end if;
166
  end process lsw_c1;
167
 
168
  process (Rx_Clk, rx_rst_n) is
169
  begin  -- process
170
    if rx_rst_n = '0' then              -- asynchronous reset (active low)
171
      RxD_del <= (others => '0');
172
      RxC_del <= (others => '0');
173
    elsif Rx_Clk'event and Rx_Clk = '1' then  -- rising clock edge
174
      RxD_del <= RxD;
175
      RxC_del <= RxC;
176
    end if;
177
  end process;
178
 
179
  -- Reading of ethernet data
180
  rdp1 : process (Rx_Clk, rx_rst_n)
181
  begin  -- process rdp1
182
    if rx_rst_n = '0' then              -- asynchronous reset (active low)
183
      r <= RCV_REGS_INI;
184
    elsif Rx_Clk'event and Rx_Clk = '1' then  -- rising clock edge
185
      r <= r_n;
186
    end if;
187
  end process rdp1;
188
 
189
  rdp2 : process (RxC, RxC_Sw, RxD, RxD_Sw, ack_fifo_full, my_ether_type,
190
                  my_mac, r, r.arg(15 downto 10), r.arg(31 downto 16),
191
                  r.cmd(15 downto 0), r.cmd(31 downto 16), r.crc32, r.dbg(0),
192
                  r.dbg(1), r.dbg(2), r.dbg(3), r.mac_addr, r.state,
193
                  r.update_flag)
194
 
195
    variable ack_pkt_in   : pkt_ack;
196
    variable v_mac_addr   : std_logic_vector(47 downto 0);
197
    variable v_cmd, v_arg : std_logic_vector(31 downto 0);
198
    variable v_crc        : std_logic_vector(31 downto 0);
199
    variable v_proto      : std_logic_vector(31 downto 0);
200
 
201
  begin  -- process
202
    c   <= RCV_COMB_DEFAULT;
203
    r_n <= r;
204
    dbg <= "1111";
205
    case r.state is
206
      when ST_RCV_IDLE =>
207
        dbg <= "0000";
208
        -- We must be prepared to one of two possible events
209
        -- Either we receive the SOF in the 0-th lane (and then we proceed
210
        -- normally) or we receive the SOF in the 4-th lane (and then we have
211
        -- to switch lanes, delaying 4 of them).
212
        if RxC = b"00011111" and RxD = x"55_55_55_fb_07_07_07_07" then
213
          -- shifted lanes
214
          -- switch on the "lane shifter" and go to the state,
215
          -- where we can check the proper preamble after lane switching
216
          r_n.swap_lanes <= '1';
217
          r_n.state      <= ST_CHECK_PREAMB;
218
        elsif RxC = b"00000001" and RxD = x"d5_55_55_55_55_55_55_fb" then
219
          -- normal lanes
220
          r_n.swap_lanes <= '0';
221
          r_n.crc32      <= (others => '1');
222
          r_n.state      <= ST_RCV_HEADER1;
223
        end if;
224
      when ST_CHECK_PREAMB =>
225
        dbg <= "0001";
226
        if RxC_Sw = b"00000001" and RxD_Sw = x"d5_55_55_55_55_55_55_fb" then
227
          r_n.crc32 <= (others => '1');
228
          r_n.state <= ST_RCV_HEADER1;
229
        else
230
          -- interrupted preamble reception
231
          r_n.state <= ST_RCV_IDLE;
232
        end if;
233
      when ST_RCV_HEADER1 =>
234
        dbg <= "0010";
235
        if RxC_Sw = b"00000000" then
236
          r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
237
          -- Change the order of bytes!
238
          for i in 0 to 5 loop
239
            v_mac_addr(47-i*8 downto 40-i*8) := RxD_Sw(i*8+7 downto i*8);
240
          end loop;  -- i
241
          if v_mac_addr /= my_mac then
242
            -- This packet is not for us - ignore it!
243
            r_n.state <= ST_RCV_WAIT_IDLE;
244
          else
245
            -- Our packet!
246
            r_n.count                  <= 0;
247
            -- Read the lower 16 bits of the sender address
248
            -- Again, we have to change the order of bytes!
249
            r_n.mac_addr(39 downto 32) <= RxD_Sw(63 downto 56);
250
            r_n.mac_addr(47 downto 40) <= RxD_Sw(55 downto 48);
251
            r_n.state                  <= ST_RCV_HEADER2;
252
          end if;
253
        else
254
          -- packet broken?
255
          r_n.state <= ST_RCV_IDLE;
256
        end if;
257
      when ST_RCV_HEADER2 =>
258
        dbg <= "0010";
259
        if RxC_Sw = b"00000000" then
260
          r_n.crc32  <= newcrc32_d64(RxD_Sw, r.crc32);
261
          v_mac_addr := r.mac_addr;
262
          for i in 0 to 3 loop
263
            v_mac_addr(31-i*8 downto 24-i*8) := RxD_Sw(i*8+7 downto i*8);
264
          end loop;  -- i
265
          --v_mac_addr(47 downto 16) := RxD_Sw(31 downto 0);
266
          r_n.mac_addr <= v_mac_addr;
267
          -- In the rest of this 64-bit word, we receive the protocol ID
268
          -- and version
269
          for i in 0 to 3 loop
270
            v_proto(i*8+7 downto i*8) := RxD_Sw(63-i*8 downto 56-i*8);
271
          end loop;  -- i
272
          -- Check if the proto id is correct
273
          if v_proto = C_PROTO_ID then
274
            r_n.state <= ST_RCV_CMD;
275
          else
276
            r_n.state <= ST_RCV_IDLE;
277
          end if;
278
        else
279
          -- packet broken?
280
          r_n.state <= ST_RCV_IDLE;
281
        end if;
282
      when ST_RCV_CMD =>
283
        if RxC_Sw = b"0000_0000" then
284
          r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
285
          -- Copy the command, changing order of bytes!
286
          for i in 0 to 3 loop
287
            r_n.cmd(i*8+7 downto i*8) <= RxD_Sw(31-i*8 downto 24-i*8);
288
          end loop;  -- i          
289
          -- Copy the argument, changing order of bytes!
290
          for i in 0 to 3 loop
291
            r_n.arg(i*8+7 downto i*8) <= RxD_Sw(63-i*8 downto 56-i*8);
292
          end loop;  -- i
293
          r_n.state <= ST_RCV_TRAILER;
294
        -- Currently we ignore rest of the packet!
295
        else
296
          -- packet broken?
297
          r_n.state <= ST_RCV_IDLE;
298
        end if;
299
      when ST_RCV_TRAILER =>
300
        -- No detection of too long frames!
301
        dbg <= "0110";
302
        if RxC_Sw /= b"0000_0000" then
303
          -- It should be a packet with the checksum
304
          -- The EOF may be on any of 8th positions.
305
          -- To avoid too big combinational functions,
306
          -- we handle it in a few states (but this increases requirements
307
          -- on IFC!)
308
          -- Current implementation assumes fixed length of frames
309
          -- but the optimal one should probably pass received data for further
310
          -- checking, why this machine continues to receive next frame...
311
          if RxC_Sw = b"1111_1100" then
312
            v_crc     := r.crc32;
313
            v_crc     := newcrc32_d16(RxD_Sw(15 downto 0), v_crc);
314
            r_n.crc32 <= v_crc;
315
            if (RxD_Sw(23 downto 16) = x"fd") and
316
              (v_crc = x"c704dd7b") then
317
              -- Correct packet, go to processing
318
              r_n.peer_mac <= r.mac_addr;
319
              r_n.state    <= ST_RCV_PROCESS;
320
            else
321
              -- Wrong CRC or EOF
322
              r_n.state <= ST_RCV_IDLE;
323
            end if;
324
          else
325
            -- Wrong packet
326
            r_n.state <= ST_RCV_IDLE;
327
          end if;
328
        else
329
          -- Ignore received data, only updating the checksum
330
          r_n.crc32 <= newcrc32_d64(RxD_Sw, r.crc32);
331
        end if;
332
      when ST_RCV_PROCESS =>
333
        dbg <= "0111";
334
        case to_integer(unsigned(r.cmd(31 downto 16))) is
335 18 wzab
          -- Handle commands, which require immediate action
336
          when FCMD_START =>
337 15 wzab
            r_n.dbg(0)        <= not r.dbg(0);
338
            -- Start transmission command
339
            r_n.transmit_data <= '1';
340 18 wzab
          when FCMD_STOP =>
341 15 wzab
            r_n.dbg(1)        <= not r.dbg(1);
342
            -- Stop transmission command
343
            r_n.transmit_data <= '0';
344 18 wzab
          when FCMD_RESET =>
345
            r_n.dbg(3)  <= not r.dbg(3);
346
            -- Restart the whole block(?)
347 15 wzab
            r_n.restart <= '1';
348 18 wzab
          when others =>
349
            null;
350 15 wzab
        end case;
351 18 wzab
        -- All commands are written to the acknowledge and commands
352
        -- FIFO, so that they will be handled by the descriptor manager
353
        if ack_fifo_full = '0' then
354
          ack_pkt_in.cmd   := unsigned(r.cmd(31 downto 16));
355
          ack_pkt_in.pkt   := unsigned(r.arg);
356
          ack_pkt_in.seq   := unsigned(r.cmd(15 downto 0));
357
          c.ack_fifo_din   <= pkt_ack_to_stlv(ack_pkt_in);
358
          c.ack_fifo_wr_en <= '1';
359
        end if;
360
        r_n.state <= ST_RCV_UPDATE;
361 15 wzab
      when ST_RCV_UPDATE =>
362
        dbg             <= "1000";
363
        r_n.update_flag <= not r.update_flag;
364
        r_n.state       <= ST_RCV_IDLE;
365
      when ST_RCV_WAIT_IDLE =>
366
        dbg <= "1001";
367
        if RxC_Sw = b"1111_1111" then
368
          r_n.state <= ST_RCV_IDLE;
369
        end if;
370
      when others => null;
371
    end case;
372
  end process rdp2;
373
 
374
  -- Synchronization of the reset signal for the Rx_Clk domain
375
  process (Rx_Clk, rst_n)
376
  begin  -- process
377
    if rst_n = '0' then                 -- asynchronous reset (active low)
378
      rx_rst_n_0 <= '0';
379
      rx_rst_n_1 <= '0';
380
      rx_rst_n   <= '0';
381
    elsif Rx_Clk'event and Rx_Clk = '1' then  -- rising clock edge
382
      rx_rst_n_0 <= rst_n;
383
      rx_rst_n_1 <= rx_rst_n_0;
384
      rx_rst_n   <= rx_rst_n_1;
385
    end if;
386
  end process;
387
 
388
 
389
  -- Synchronization of output signals between the clock domains
390
  process (clk, rst_n)
391
  begin  -- process
392
    if rst_n = '0' then                 -- asynchronous reset (active low)
393
      peer_mac      <= (others => '0');
394
      transmit_data <= '0';
395
      restart       <= '0';
396
      update_flag_0 <= '0';
397
      update_flag_1 <= '0';
398
      update_flag   <= '0';
399
    elsif clk'event and clk = '1' then  -- rising clock edge
400
      -- Synchronization of the update_flag
401
      update_flag_0 <= r.update_flag;
402
      update_flag_1 <= update_flag_0;
403
      update_flag   <= update_flag_1;
404
      -- When update flag has changed, rewrite synchronized fields
405
      if update_flag /= update_flag_1 then
406
        peer_mac      <= r.peer_mac;
407
        transmit_data <= r.transmit_data;
408
        restart       <= r.restart;
409
      end if;
410
    end if;
411
  end process;
412
 
413
end beh1;

powered by: WebSVN 2.1.0

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