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

Subversion Repositories fade_ether_protocol

[/] [fade_ether_protocol/] [trunk/] [old_stable_version/] [FPGA_no_MAC/] [src/] [common/] [eth_sender4.vhd] - Blame information for rev 34

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 wzab
-------------------------------------------------------------------------------
2
-- Title      : FPGA Ethernet interface - block sending packets via MII Phy
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : desc_manager.vhd
6
-- Author     : Wojciech M. Zabolotny (wzab@ise.pw.edu.pl)
7
-- License    : BSD License
8
-- Company    : 
9
-- Created    : 2012-03-30
10 7 wzab
-- Last update: 2013-06-16
11 3 wzab
-- Platform   : 
12
-- Standard   : VHDL'93
13
-------------------------------------------------------------------------------
14
-- Description: This file implements the state machine, which manages the
15
-- table of packet descriptors, used to resend only not confirmed packets
16
-------------------------------------------------------------------------------
17
-- Copyright (c) 2012 
18
-------------------------------------------------------------------------------
19
-- Revisions  :
20
-- Date        Version  Author  Description
21
-- 2012-03-30  1.0      WZab      Created
22
-------------------------------------------------------------------------------
23
library ieee;
24
use ieee.std_logic_1164.all;
25
use ieee.numeric_std.all;
26
library work;
27
use work.PCK_CRC32_D4.all;
28
 
29
entity eth_sender is
30
 
31
  port (
32
    -- Configuration
33
    peer_mac      : in  std_logic_vector(47 downto 0);
34
    my_mac        : in  std_logic_vector(47 downto 0);
35
    my_ether_type : in  std_logic_vector(15 downto 0);
36
    set_number    : in  unsigned(15 downto 0);
37
    pkt_number    : in  unsigned(15 downto 0);
38
    retry_number  : in  unsigned(15 downto 0);
39
    transm_delay  : in  unsigned(31 downto 0);
40
    -- System interface
41
    clk           : in  std_logic;
42
    rst_n         : in  std_logic;
43
    -- Control interface
44
    ready         : out std_logic;
45
    start         : in  std_logic;
46
    -- Data memory interface
47
    tx_mem_addr   : out std_logic_vector(13 downto 0);
48
    tx_mem_data   : in  std_logic_vector(31 downto 0);
49
    -- TX Phy interface
50
    Tx_Clk        : in  std_logic;
51
    Tx_En         : out std_logic;
52
    TxD           : out std_logic_vector(3 downto 0)
53
    );
54
 
55
end eth_sender;
56
 
57
 
58
architecture beh1 of eth_sender is
59
 
60
  type T_ETH_SENDER_STATE is (WST_IDLE, WST_SEND_PREAMB, WST_SEND_SOF,
61
                              WST_SEND_HEADER, WST_SEND_DATA, WST_SEND_CRC,
62
                              WST_SEND_COMPLETED);
63
 
64
  type T_ETH_SENDER_REGS is record
65
    state    : T_ETH_SENDER_STATE;
66
    ready    : std_logic;
67
    count    : integer;
68
    nibble   : integer;
69
    mem_addr : unsigned (7 downto 0);
70
    crc32    : std_logic_vector(31 downto 0);
71
  end record;
72
 
73
  constant ETH_SENDER_REGS_INI : T_ETH_SENDER_REGS := (
74
    state    => WST_IDLE,
75
    ready    => '1',
76
    count    => 0,
77
    nibble   => 0,
78
    mem_addr => (others => '0'),
79
    crc32    => (others => '0')
80
    ) ;
81
 
82
  signal r, r_n : T_ETH_SENDER_REGS := ETH_SENDER_REGS_INI;
83
 
84
  type T_ETH_SENDER_COMB is record
85
    TxD      : std_logic_vector(3 downto 0);
86
    Tx_En    : std_logic;
87
    mem_addr : unsigned(7 downto 0);
88
  end record;
89
 
90
  constant ETH_SENDER_COMB_DEFAULT : T_ETH_SENDER_COMB := (
91
    TxD      => (others => '0'),
92
    Tx_En    => '0',
93
    mem_addr => (others => '0')
94
    );
95
 
96
  signal c : T_ETH_SENDER_COMB := ETH_SENDER_COMB_DEFAULT;
97
 
98
  signal s_header     : std_logic_vector(6*32-1 downto 0) := (others => '0');
99
  constant HEADER_LEN : integer                           := 6*8;  -- 6 words,
100
                                                                   -- 8 nibbles each
101
 
102
  function select_nibble (
103
    constant vec        : std_logic_vector;
104
    constant nibble_num : integer)
105
    return std_logic_vector is
106
    variable byte_num : integer;
107
    variable v_byte   : std_logic_vector(7 downto 0);
108
    variable v_nibble : std_logic_vector(3 downto 0);
109
  begin
110
    -- first select byte
111
    byte_num := nibble_num / 2;
112
    v_byte   := vec(vec'left-byte_num*8 downto vec'left-byte_num*8-7);
113
    -- then select nibble (lower nibble is sent first!)
114
    if nibble_num mod 2 = 0 then
115
      v_nibble := v_byte(3 downto 0);
116
    else
117
      v_nibble := v_byte(7 downto 4);
118
    end if;
119
    return v_nibble;
120
  end select_nibble;
121
 
122
  function rev(a : in std_logic_vector)
123
    return std_logic_vector is
124
    variable result : std_logic_vector(a'range);
125
    alias aa        : std_logic_vector(a'reverse_range) is a;
126
  begin
127
    for i in aa'range loop
128
      result(i) := aa(i);
129
    end loop;
130
    return result;
131
  end;  -- function reverse_any_bus
132
 
133
  signal tx_rst_n, tx_rst_n_0, tx_rst_n_1          : std_logic := '0';
134
  signal update_flag_0, update_flag_1, update_flag : std_logic := '0';
135
 
136
  signal start_0, tx_start, tx_start_1, tx_start_0 : std_logic := '0';
137
  signal tx_ready, ready_0, ready_1                : std_logic := '0';
138
 
139
  type T_STATE1 is (ST1_IDLE, ST1_WAIT_NOT_READY, ST1_WAIT_NOT_START,
140
                    ST1_WAIT_READY);
141
  signal state1 : T_STATE1;
142
 
143
  type T_STATE2 is (ST2_IDLE, ST2_WAIT_NOT_READY, ST2_WAIT_READY);
144
  signal state2 : T_STATE2;
145
begin  -- beh1
146
 
147
  -- Packet header
148
  s_header <= peer_mac & my_mac & my_ether_type & x"a5a5" &
149
              std_logic_vector(set_number(15 downto 0)) &
150
              std_logic_vector(pkt_number(5 downto 0)) &
151
              std_logic_vector(retry_number(9 downto 0)) &
152
              std_logic_vector(transm_delay);
153
  -- Connection of the signals
154
 
155
  -- The memory address is built from the packet number (6 bits) and word
156
  -- number (8 bits)
157
  tx_mem_addr <= std_logic_vector(pkt_number(5 downto 0)) & std_logic_vector(c.mem_addr);
158
 
159
  -- Main state machine used to send the packet
160
  -- W calej maszynie trzeba jeszcze dodac obsluge kolizji!!!
161
  -- Oprocz tego trzeba przeanalizowac poprawnosc przejsc miedzy domenami zegara
162
 
163
 
164
  snd1 : process (Tx_Clk, tx_rst_n)
165
  begin
166
    if tx_rst_n = '0' then              -- asynchronous reset (active low)
167
      r     <= ETH_SENDER_REGS_INI;
168
      TxD   <= (others => '0');
169
      Tx_En <= '0';
170
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
171
      r     <= r_n;
172
      -- To minimize glitches and propagation delay, let's add pipeline register
173
      Tx_En <= c.Tx_En;
174
      TxD   <= c.TxD;
175
    end if;
176
  end process snd1;  -- snd1
177
 
178
  snd2 : process (r, s_header, tx_mem_data, tx_start)
179
    variable v_TxD : std_logic_vector(3 downto 0);
180
  begin  -- process snd1
181
    -- default values
182
    c   <= ETH_SENDER_COMB_DEFAULT;
183
    r_n <= r;
184
    case r.state is
185
      when WST_IDLE =>
186
        r_n.ready <= '1';
187
        if tx_start = '1' then
188
          r_n.ready <= '0';
189
          r_n.state <= WST_SEND_PREAMB;
190
          r_n.count <= 15;
191
        end if;
192
      when WST_SEND_PREAMB =>
193
        -- Trzeba dodac wykrywanie kolizji!
194
        c.TxD     <= x"5";
195
        c.Tx_En   <= '1';
196
        r_n.count <= r.count - 1;
197
        if r.count = 1 then
198
          r_n.state <= WST_SEND_SOF;
199
        end if;
200
      when WST_SEND_SOF =>
201
        c.TxD     <= x"D";
202
        c.Tx_En   <= '1';
203
        -- Prepare for sending of header
204
        r_n.crc32 <= (others => '1');
205
        r_n.state <= WST_SEND_HEADER;
206
        r_n.count <= 0;
207
      when WST_SEND_HEADER =>
208
        v_TxD     := select_nibble(s_header, r.count);
209
        c.TxD     <= v_TxD;
210
        c.Tx_En   <= '1';
211
        r_n.crc32 <= nextCRC32_D4(rev(v_TxD), r.crc32);
212
        if r.count < HEADER_LEN-1 then
213
          r_n.count <= r.count + 1;
214
        else
215
          r_n.count    <= 0;
216
          r_n.nibble   <= 0;
217
          r_n.mem_addr <= (others => '0');
218
          c.mem_addr   <= (others => '0');
219
          r_n.state    <= WST_SEND_DATA;
220
        end if;
221
      when WST_SEND_DATA =>
222
        -- send the data nibble by nibble
223 5 wzab
        v_TxD     := select_nibble(tx_mem_data, r.nibble);
224 3 wzab
        c.TxD     <= v_TxD;
225
        c.Tx_En   <= '1';
226
        r_n.crc32 <= nextCRC32_D4(rev(v_TxD), r.crc32);
227
        if r.nibble < 7 then
228
          r_n.nibble <= r.nibble + 1;
229
          c.mem_addr <= r.mem_addr;
230
        else
231
          r_n.nibble <= 0;
232
          -- Check, if we have sent all the data
233
          if r.mem_addr < 255 then
234
            r_n.mem_addr <= r.mem_addr + 1;
235
            c.mem_addr   <= r.mem_addr + 1;
236
          else
237
            -- We send the CRC
238
            r_n.state <= WST_SEND_CRC;
239
          end if;
240
        end if;
241
      when WST_SEND_CRC =>
242 5 wzab
        v_TxD   := r.crc32(31-r.nibble*4 downto 28-r.nibble*4);
243 3 wzab
        c.TxD   <= not rev(v_TxD);
244
        c.Tx_En <= '1';
245
        if r.nibble < 7 then
246
          r_n.nibble <= r.nibble + 1;
247
        else
248 6 wzab
          r_n.count <= 24;              -- generate the IFG - 24 nibbles = 96
249 3 wzab
                                        -- bits
250
          r_n.state <= WST_SEND_COMPLETED;
251
        end if;
252
      when WST_SEND_COMPLETED =>
253
        if r.count > 0 then
254
          r_n.count <= r.count - 1;
255
        else
256
          r_n.ready <= '1';
257
          r_n.state <= WST_IDLE;
258
        end if;
259
    end case;
260
  end process snd2;
261
 
262
 
263
  -- Synchronization of the reset signal for the Tx_Clk domain
264
  process (Tx_Clk, rst_n)
265
  begin  -- process
266
    if rst_n = '0' then                 -- asynchronous reset (active low)
267
      tx_rst_n_0 <= '0';
268
      tx_rst_n_1 <= '0';
269
      tx_rst_n   <= '0';
270
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
271
      tx_rst_n_0 <= rst_n;
272
      tx_rst_n_1 <= tx_rst_n_0;
273
      tx_rst_n   <= tx_rst_n_1;
274
    end if;
275
  end process;
276
 
277
  -- Synchronization of signals passing clock domains
278
  -- Signal start is sent from the Clk domain.
279
  -- When it is asserted, we must immediately deassert signal ready,
280
  -- then generate the synchronized start and after internal ready
281
  -- is asserted, we can output it again...
282
 
283
  -- Ustawienie na 1 takt zegara "clk" sygnalu start powinno zainicjowac wysylanie
284
  -- w tym bloku musimy zadbac o stosowne wydluzenie sygnalu start i jego synchronizacje
285
  -- miedzy domenami zegara...
286
  process (clk, rst_n)
287
  begin  -- process
288
    if rst_n = '0' then                 -- asynchronous reset (active low)
289
      ready   <= '0';
290 7 wzab
      ready_0 <= '0';
291 3 wzab
      ready_1 <= '0';
292
      state2  <= ST2_IDLE;
293
    elsif clk'event and clk = '1' then  -- rising clock edge
294
      ready_1 <= tx_ready;
295
      ready_0 <= ready_1;
296
      case state2 is
297
        when ST2_IDLE =>
298
          if start = '1' and ready_0 = '1' then
299
            start_0 <= '1';
300
            ready   <= '0';
301
            state2  <= ST2_WAIT_NOT_READY;
302
          else
303
            ready <= ready_0;           -- Needed to provide correct start!
304
          end if;
305
        when ST2_WAIT_NOT_READY =>
306
          if ready_0 = '0' then
307
            start_0 <= '0';
308
            state2  <= ST2_WAIT_READY;
309
          end if;
310
        when ST2_WAIT_READY =>
311
          if ready_0 = '1' then
312
            ready  <= '1';
313
            state2 <= ST2_IDLE;
314
          end if;
315
        when others => null;
316
      end case;
317
    end if;
318
  end process;
319
 
320
  process (Tx_Clk, tx_rst_n)
321
  begin  -- process
322
    if tx_rst_n = '0' then              -- asynchronous reset (active low)
323
      tx_start   <= '0';
324
      tx_start_0 <= '0';
325
      state1     <= ST1_IDLE;
326
      tx_ready   <= '1';
327
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
328 7 wzab
      tx_start_0 <= start_0;
329 3 wzab
      tx_start   <= tx_start_0;
330
      case state1 is
331
        when ST1_IDLE =>
332
          if tx_start = '1' then
333
            tx_ready <= '0';            -- this should cause tx_start to go low
334
            state1   <= ST1_WAIT_NOT_READY;
335
          end if;
336
        when ST1_WAIT_NOT_READY =>
337
          if r.ready = '0' then
338
            state1 <= ST1_WAIT_NOT_START;
339
          end if;
340
        when ST1_WAIT_NOT_START =>
341
          if tx_start = '0' then
342
            state1 <= ST1_WAIT_READY;
343
          end if;
344
        when ST1_WAIT_READY =>
345
          if r.ready = '1' then
346
            tx_ready <= '1';
347
            state1   <= ST1_IDLE;
348
          end if;
349
        when others => null;
350
      end case;
351
    end if;
352
  end process;
353
 
354
end beh1;

powered by: WebSVN 2.1.0

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