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_sender8.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_D8.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(7 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
    byte     : 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
    byte     => 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(7 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*4;  -- 6 words,
100
                                                                   -- 4 bytes each
101
 
102
 
103
  function select_byte (
104
    constant vec      : std_logic_vector;
105
    constant byte_num : integer)
106
    return std_logic_vector is
107
    variable v_byte : std_logic_vector(7 downto 0);
108
  begin
109
    -- first select byte
110
    v_byte := vec(vec'left-byte_num*8 downto vec'left-byte_num*8-7);
111
    return v_byte;
112
  end select_byte;
113
 
114
  function rev(a : in std_logic_vector)
115
    return std_logic_vector is
116
    variable result : std_logic_vector(a'range);
117
    alias aa        : std_logic_vector(a'reverse_range) is a;
118
  begin
119
    for i in aa'range loop
120
      result(i) := aa(i);
121
    end loop;
122
    return result;
123
  end;  -- function reverse_any_bus
124
 
125
  signal tx_rst_n, tx_rst_n_0, tx_rst_n_1          : std_logic := '0';
126
  signal update_flag_0, update_flag_1, update_flag : std_logic := '0';
127
 
128
  signal start_0, tx_start, tx_start_1, tx_start_0 : std_logic := '0';
129
  signal tx_ready, ready_0, ready_1                : std_logic := '0';
130
 
131
  type T_STATE1 is (ST1_IDLE, ST1_WAIT_NOT_READY, ST1_WAIT_NOT_START,
132
                    ST1_WAIT_READY);
133
  signal state1 : T_STATE1;
134
 
135
  type T_STATE2 is (ST2_IDLE, ST2_WAIT_NOT_READY, ST2_WAIT_READY);
136
  signal state2 : T_STATE2;
137
begin  -- beh1
138
 
139
  -- Packet header
140
  s_header <= peer_mac & my_mac & my_ether_type & x"a5a5" &
141
              std_logic_vector(set_number(15 downto 0)) &
142
              std_logic_vector(pkt_number(5 downto 0)) &
143
              std_logic_vector(retry_number(9 downto 0)) &
144
              std_logic_vector(transm_delay);
145
  -- Connection of the signals
146
 
147
  -- The memory address is built from the packet number (6 bits) and word
148
  -- number (8 bits)
149
  tx_mem_addr <= std_logic_vector(pkt_number(5 downto 0)) & std_logic_vector(c.mem_addr);
150
 
151
  -- Main state machine used to send the packet
152
  -- W calej maszynie trzeba jeszcze dodac obsluge kolizji!!!
153
  -- Oprocz tego trzeba przeanalizowac poprawnosc przejsc miedzy domenami zegara
154
 
155
 
156
  snd1 : process (Tx_Clk, tx_rst_n)
157
  begin
158
    if tx_rst_n = '0' then              -- asynchronous reset (active low)
159
      r     <= ETH_SENDER_REGS_INI;
160
      TxD   <= (others => '0');
161
      Tx_En <= '0';
162
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
163
      r     <= r_n;
164
      -- To minimize glitches and propagation delay, let's add pipeline register
165
      Tx_En <= c.Tx_En;
166
      TxD   <= c.TxD;
167
    end if;
168
  end process snd1;  -- snd1
169
 
170
  snd2 : process (r, s_header, tx_mem_data, tx_start)
171
    variable v_TxD : std_logic_vector(7 downto 0);
172
  begin  -- process snd1
173
    -- default values
174
    c   <= ETH_SENDER_COMB_DEFAULT;
175
    r_n <= r;
176
    case r.state is
177
      when WST_IDLE =>
178
        r_n.ready <= '1';
179
        if tx_start = '1' then
180
          r_n.ready <= '0';
181
          r_n.state <= WST_SEND_PREAMB;
182
          r_n.count <= 7;
183
        end if;
184
      when WST_SEND_PREAMB =>
185
        -- Trzeba dodac wykrywanie kolizji!
186
        c.TxD     <= x"55";
187
        c.Tx_En   <= '1';
188
        r_n.count <= r.count - 1;
189
        if r.count = 1 then
190
          r_n.state <= WST_SEND_SOF;
191
        end if;
192
      when WST_SEND_SOF =>
193
        c.TxD     <= x"D5";
194
        c.Tx_En   <= '1';
195
        -- Prepare for sending of header
196
        r_n.crc32 <= (others => '1');
197
        r_n.state <= WST_SEND_HEADER;
198
        r_n.count <= 0;
199
      when WST_SEND_HEADER =>
200
        v_TxD     := select_byte(s_header, r.count);
201
        c.TxD     <= v_TxD;
202
        c.Tx_En   <= '1';
203
        r_n.crc32 <= nextCRC32_D8(rev(v_TxD), r.crc32);
204
        if r.count < HEADER_LEN-1 then
205
          r_n.count <= r.count + 1;
206
        else
207
          r_n.count    <= 0;
208
          r_n.byte     <= 0;
209
          r_n.mem_addr <= (others => '0');
210
          c.mem_addr   <= (others => '0');
211
          r_n.state    <= WST_SEND_DATA;
212
        end if;
213
      when WST_SEND_DATA =>
214
        -- send the data byte by byte
215
        v_TxD     := select_byte(tx_mem_data, r.byte);
216
        c.TxD     <= v_TxD;
217
        c.Tx_En   <= '1';
218
        r_n.crc32 <= nextCRC32_D8(rev(v_TxD), r.crc32);
219
        if r.byte < 3 then
220
          r_n.byte   <= r.byte + 1;
221
          c.mem_addr <= r.mem_addr;
222
        else
223
          r_n.byte <= 0;
224
          -- Check, if we have sent all the data
225
          if r.mem_addr < 255 then
226
            r_n.mem_addr <= r.mem_addr + 1;
227
            c.mem_addr   <= r.mem_addr + 1;
228
          else
229
            -- We send the CRC
230
            r_n.state <= WST_SEND_CRC;
231
          end if;
232
        end if;
233
      when WST_SEND_CRC =>
234 11 wzab
        v_TxD   := r.crc32(31-r.byte*8 downto 24-r.byte*8);
235 3 wzab
        c.TxD   <= not rev(v_TxD);
236
        c.Tx_En <= '1';
237
        if r.byte < 3 then
238
          r_n.byte <= r.byte + 1;
239
        else
240 6 wzab
          r_n.count <= 12;              -- generate the IFG - 12 bytes = 96
241 3 wzab
                                        -- bits
242
          r_n.state <= WST_SEND_COMPLETED;
243
        end if;
244
      when WST_SEND_COMPLETED =>
245
        if r.count > 0 then
246
          r_n.count <= r.count - 1;
247
        else
248
          r_n.ready <= '1';
249
          r_n.state <= WST_IDLE;
250
        end if;
251
    end case;
252
  end process snd2;
253
 
254
 
255
  -- Synchronization of the reset signal for the Tx_Clk domain
256
  process (Tx_Clk, rst_n)
257
  begin  -- process
258
    if rst_n = '0' then                 -- asynchronous reset (active low)
259
      tx_rst_n_0 <= '0';
260
      tx_rst_n_1 <= '0';
261
      tx_rst_n   <= '0';
262
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
263
      tx_rst_n_0 <= rst_n;
264
      tx_rst_n_1 <= tx_rst_n_0;
265
      tx_rst_n   <= tx_rst_n_1;
266
    end if;
267
  end process;
268
 
269
  -- Synchronization of signals passing clock domains
270
  -- Signal start is sent from the Clk domain.
271
  -- When it is asserted, we must immediately deassert signal ready,
272
  -- then generate the synchronized start and after internal ready
273
  -- is asserted, we can output it again...
274
 
275
  -- Ustawienie na 1 takt zegara "clk" sygnalu start powinno zainicjowac wysylanie
276
  -- w tym bloku musimy zadbac o stosowne wydluzenie sygnalu start i jego synchronizacje
277
  -- miedzy domenami zegara...
278
  process (clk, rst_n)
279
  begin  -- process
280
    if rst_n = '0' then                 -- asynchronous reset (active low)
281
      ready   <= '0';
282
      ready_1 <= '0';
283
      ready_0 <= '0';
284
      state2  <= ST2_IDLE;
285
    elsif clk'event and clk = '1' then  -- rising clock edge
286
      ready_1 <= tx_ready;
287
      ready_0 <= ready_1;
288
      case state2 is
289
        when ST2_IDLE =>
290
          if start = '1' and ready_0 = '1' then
291
            start_0 <= '1';
292
            ready   <= '0';
293
            state2  <= ST2_WAIT_NOT_READY;
294
          else
295
            ready <= ready_0;           -- Needed to provide correct start!
296
          end if;
297
        when ST2_WAIT_NOT_READY =>
298
          if ready_0 = '0' then
299
            start_0 <= '0';
300
            state2  <= ST2_WAIT_READY;
301
          end if;
302
        when ST2_WAIT_READY =>
303
          if ready_0 = '1' then
304
            ready  <= '1';
305
            state2 <= ST2_IDLE;
306
          end if;
307
        when others => null;
308
      end case;
309
    end if;
310
  end process;
311
 
312
  process (Tx_Clk, tx_rst_n)
313
  begin  -- process
314
    if tx_rst_n = '0' then              -- asynchronous reset (active low)
315
      tx_start   <= '0';
316
      tx_start_0 <= '0';
317
      state1     <= ST1_IDLE;
318
      tx_ready   <= '1';
319
    elsif Tx_Clk'event and Tx_Clk = '1' then  -- rising clock edge
320 7 wzab
      tx_start_0 <= start_0;
321 3 wzab
      tx_start   <= tx_start_0;
322
      case state1 is
323
        when ST1_IDLE =>
324
          if tx_start = '1' then
325
            tx_ready <= '0';            -- this should cause tx_start to go low
326
            state1   <= ST1_WAIT_NOT_READY;
327
          end if;
328
        when ST1_WAIT_NOT_READY =>
329
          if r.ready = '0' then
330
            state1 <= ST1_WAIT_NOT_START;
331
          end if;
332
        when ST1_WAIT_NOT_START =>
333
          if tx_start = '0' then
334
            state1 <= ST1_WAIT_READY;
335
          end if;
336
        when ST1_WAIT_READY =>
337
          if r.ready = '1' then
338
            tx_ready <= '1';
339
            state1   <= ST1_IDLE;
340
          end if;
341
        when others => null;
342
      end case;
343
    end if;
344
  end process;
345
 
346
end beh1;

powered by: WebSVN 2.1.0

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