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/] [desc_manager_simple.vhd] - Blame information for rev 45

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 wzab
-------------------------------------------------------------------------------
2
-- Title      : FPGA Ethernet interface - descriptor manager
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 45 wzab
-- Last update: 2017-01-23
11 15 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
 
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
use ieee.numeric_std.all;
28
use std.textio.all;
29
library work;
30
use work.pkt_ack_pkg.all;
31
use work.desc_mgr_pkg.all;
32
use work.pkt_desc_pkg.all;
33
 
34
entity desc_memory is
35
 
36
  port (
37
    clk       : in  std_logic;
38
    desc_we   : in  std_logic;
39
    desc_addr : in  integer range 0 to N_OF_PKTS-1;
40
    desc_out  : in  pkt_desc;
41
    desc_in   : out pkt_desc);
42
 
43
end desc_memory;
44
 
45
architecture beh1 of desc_memory is
46
 
47
  type T_PKT_DESC_MEM is array (0 to N_OF_PKTS-1) of std_logic_vector(pkt_desc_width-1 downto 0);
48
  signal desc_mem : T_PKT_DESC_MEM                              := (others => (others => '0'));
49
  signal din      : std_logic_vector(pkt_desc_width-1 downto 0) := (others => '0');
50
  signal dout     : std_logic_vector(pkt_desc_width-1 downto 0) := (others => '0');
51
  signal rdaddr   : integer range 0 to N_OF_PKTS-1;
52
 
53 43 wzab
 
54 15 wzab
begin  -- beh1
55
 
56
  din     <= pkt_desc_to_stlv(desc_out);
57
  desc_in <= stlv_to_pkt_desc(dout);
58
 
59
  process (clk)
60
  begin  -- process
61
    if (clk'event and clk = '1') then   -- rising clock edge
62
      if (desc_we = '1') then
63
        desc_mem(desc_addr) <= din;
64
      end if;
65
      rdaddr <= desc_addr;
66
    end if;
67
  end process;
68
  dout <= desc_mem(rdaddr);
69
 
70
end beh1;
71
 
72
library ieee;
73
use ieee.std_logic_1164.all;
74
use ieee.numeric_std.all;
75
use std.textio.all;
76
library work;
77
use work.pkt_ack_pkg.all;
78
use work.desc_mgr_pkg.all;
79
use work.pkt_desc_pkg.all;
80
 
81
entity desc_manager is
82 43 wzab
 
83 15 wzab
  generic (
84
    LOG2_N_OF_PKTS : integer := LOG2_N_OF_PKTS;
85
    N_OF_PKTS      : integer := N_OF_PKTS
86
    );                                  -- Number of packet_logi buffers
87
 
88
  port (
89
    -- Data input interface
90
    dta              : in  std_logic_vector(63 downto 0);
91
    dta_we           : in  std_logic;
92 18 wzab
    dta_eod          : in  std_logic;
93 15 wzab
    dta_ready        : out std_logic;
94
    -- ETH Sender interface
95
    pkt_number       : out unsigned(31 downto 0);
96
    seq_number       : out unsigned(15 downto 0);
97
    cmd_response_out : out std_logic_vector(12*8-1 downto 0);
98
    snd_cmd_start    : out std_logic;
99
    snd_start        : out std_logic;
100 18 wzab
    flushed          : out std_logic;
101 15 wzab
    snd_ready        : in  std_logic;
102
 
103
    -- Data memory interface
104
    dmem_addr       : out std_logic_vector(LOG2_NWRDS_IN_PKT+LOG2_N_OF_PKTS-1 downto 0);
105
    dmem_dta        : out std_logic_vector(63 downto 0);
106
    dmem_we         : out std_logic;
107
    -- Interface to the ACK FIFO
108
    ack_fifo_empty  : in  std_logic;
109
    ack_fifo_rd_en  : out std_logic;
110
    ack_fifo_dout   : in  std_logic_vector(pkt_ack_width-1 downto 0);
111
    -- User command interface
112
    cmd_code        : out std_logic_vector(15 downto 0);
113
    cmd_seq         : out std_logic_vector(15 downto 0);
114
    cmd_arg         : out std_logic_vector(31 downto 0);
115
    cmd_run         : out std_logic;
116 18 wzab
    cmd_retr_s      : out std_logic;
117 15 wzab
    cmd_ack         : in  std_logic;
118
    cmd_response_in : in  std_logic_vector(8*12-1 downto 0);
119 26 wzab
    retr_count      : out std_logic_vector(31 downto 0);
120 15 wzab
    --
121
    transmit_data   : in  std_logic;
122
    transm_delay    : out unsigned(31 downto 0);
123
    --
124
    dbg             : out std_logic_vector(3 downto 0);
125
    --
126
    clk             : in  std_logic;
127
    rst_n           : in  std_logic);
128
 
129
end desc_manager;
130
 
131
architecture dmgr_a1 of desc_manager is
132
 
133
  constant PKT_CNT_MAX : integer := 3000;
134
 
135
 
136
  function is_bigger (
137
    constant v1, v2 : unsigned(15 downto 0))
138
    return boolean is
139
    variable res : boolean;
140
    variable tmp : unsigned(15 downto 0);
141
  begin  -- function is_bigger
142
    -- subtract v2-v1 modulo 2**16
143
    tmp := v2-v1;
144
    -- if the result is "negative" - bit 15 is '1'
145
    -- and we consider v1 to be "bigger" (in modulo sense) than v2
146
    if tmp(15) = '1' then
147
      return true;
148
    else
149
      return false;
150
    end if;
151 43 wzab
 
152 15 wzab
  end function is_bigger;
153
 
154
  -- To simplify description of state machines, all registers are grouped
155
  -- in a record :
156
 
157
  type T_DESC_MGR_REGS is record
158
    cmd_ack        : std_logic;
159
    cmd_ack_0      : std_logic;
160
    cmd_run        : std_logic;
161
    cmd_retr       : std_logic;
162
    cmd_code       : unsigned(15 downto 0);
163
    cmd_seq        : unsigned(15 downto 0);
164
    cmd_arg        : unsigned(31 downto 0);
165
    pkt            : unsigned(31 downto 0);
166
    cur_pkt        : unsigned(31 downto 0);
167
    seq            : unsigned(15 downto 0);
168
    ack_seq        : unsigned(15 downto 0);
169
    retr_flag      : std_logic;
170 18 wzab
    flushed        : std_logic;
171 15 wzab
    all_pkt_count  : integer range 0 to PKT_CNT_MAX;
172
    retr_pkt_count : integer range 0 to PKT_CNT_MAX;
173
    retr_delay     : unsigned(31 downto 0);
174 26 wzab
    retr_count     : unsigned(31 downto 0);
175 15 wzab
    transm_delay   : unsigned(31 downto 0);
176
    nxt            : unsigned(LOG2_N_OF_PKTS-1 downto 0);
177
    tail_ptr       : unsigned(LOG2_N_OF_PKTS-1 downto 0);
178
    head_ptr       : unsigned(LOG2_N_OF_PKTS-1 downto 0);
179
    retr_ptr       : unsigned(LOG2_N_OF_PKTS-1 downto 0);  -- Number of the packet buffer, which is retransmitted
180
                                        -- when equal to head_ptr -
181
                                        -- retransmission is finished
182
    retr_nxt       : unsigned(LOG2_N_OF_PKTS-1 downto 0);  -- buffer, which will be
183
                                        -- retransmitted next
184
                                                           -- when equal to head_ptr -- no retransmission
185
                                                           -- is performed
186
  end record;
187
 
188
  constant DESC_MGR_REGS_INI : T_DESC_MGR_REGS := (
189
    retr_delay     => (others => '0'),
190 26 wzab
    retr_count     => (others => '0'),
191
    transm_delay   => to_unsigned(16, 32),
192 15 wzab
    all_pkt_count  => 0,
193
    retr_pkt_count => 0,
194
    cmd_ack_0      => '0',
195
    cmd_ack        => '0',
196
    cmd_run        => '0',
197
    cmd_retr       => '0',
198
    cmd_code       => (others => '0'),
199
    cmd_seq        => (others => '0'),
200
    cmd_arg        => (others => '0'),
201
    pkt            => (others => '0'),
202
    seq            => (others => '0'),
203
    ack_seq        => (others => '0'),
204
    retr_flag      => '0',
205 18 wzab
    flushed        => '0',
206 15 wzab
    cur_pkt        => (others => '0'),
207
    nxt            => (others => '0'),
208
    tail_ptr       => (others => '0'),
209
    head_ptr       => (others => '0'),
210
    retr_ptr       => (others => '0'),
211
    retr_nxt       => (others => '0')
212
    );
213
 
214
  -- To simplify setting of outputs of my Mealy state machine, all combinatorial
215
  -- outputs are grouped in a record
216
  type T_DESC_MGR_COMB is record
217
    dta_buf_free  : std_logic;
218
    desc_addr     : unsigned(LOG2_N_OF_PKTS-1 downto 0);
219
    desc_we       : std_logic;
220
    ack_rd        : std_logic;
221
    snd_start     : std_logic;
222
    snd_cmd_start : std_logic;
223
    desc_out      : pkt_desc;
224
  end record;
225
 
226
  constant DESC_MGR_COMB_DEFAULT : T_DESC_MGR_COMB :=
227
    (
228
      dta_buf_free  => '0',
229
      desc_addr     => (others => '0'),
230
      desc_we       => '0',
231
      ack_rd        => '0',
232
      snd_start     => '0',
233
      snd_cmd_start => '0',
234
      desc_out      => (
235
        confirmed   => '0',
236
        valid       => '0',
237
        sent        => '0',
238 18 wzab
        flushed     => '0',
239 15 wzab
        pkt         => (others => '0'),
240
        seq         => (others => '0')
241
        )
242
      );
243
 
244
  type T_DESC_MGR_STATE is (ST_DMGR_IDLE, ST_DMGR_CMD, ST_DMGR_START, ST_DMGR_RST, ST_DMGR_RST1,
245
                            ST_DMGR_ACK1, ST_DMGR_INS1, ST_DMGR_INS2, ST_DMGR_ACK_TAIL,
246
                            ST_DMGR_ACK_TAIL_1,
247
                            ST_DMGR_RETR, ST_DMGR_RETR_2);
248
 
249
  signal desc_in : pkt_desc;
250
 
251
  signal r, r_i                      : T_DESC_MGR_REGS  := DESC_MGR_REGS_INI;
252
  signal c                           : T_DESC_MGR_COMB;
253
  signal dmgr_state, dmgr_state_next : T_DESC_MGR_STATE := ST_DMGR_RST;
254
  attribute keep                     : string;
255
  attribute keep of dmgr_state       : signal is "true";
256
 
257 20 wzab
  signal dta_buf_full   : std_logic := '0';
258
  signal dta_buf_flush  : std_logic := '0';
259
  signal stored_dta_eod : std_logic := '0';
260 15 wzab
 
261
  signal ack_pkt_in : pkt_ack;
262
 
263
  signal wrd_addr : integer range 0 to NWRDS_IN_PKT-1;  -- We use 64-bit words, so the
264
                                        -- data word address is between
265
                                        -- 0 and 1023
266
 
267
  component desc_memory
268
    port (
269
      clk       : in  std_logic;
270
      desc_we   : in  std_logic;
271
      desc_addr : in  integer range 0 to N_OF_PKTS-1;
272
      desc_out  : in  pkt_desc;
273
      desc_in   : out pkt_desc);
274
  end component;
275
 
276
 
277
begin  -- dmgr_a1
278
 
279 26 wzab
  retr_count <= std_logic_vector(r.retr_count);
280
 
281 15 wzab
  transm_delay   <= r.transm_delay;
282
  pkt_number     <= r.pkt;
283
  seq_number     <= r.seq;
284 18 wzab
  flushed        <= r.flushed;
285 15 wzab
  dta_ready      <= not dta_buf_full;
286
  snd_start      <= c.snd_start;
287
  ack_fifo_rd_en <= c.ack_rd;
288
 
289 18 wzab
  cmd_code      <= std_logic_vector(r.cmd_code);
290
  cmd_seq       <= std_logic_vector(r.cmd_seq);
291
  cmd_arg       <= std_logic_vector(r.cmd_arg);
292
  cmd_run       <= r.cmd_run;
293
  cmd_retr_s    <= r.cmd_retr;
294
  snd_cmd_start <= c.snd_cmd_start;
295
 
296 15 wzab
  ack_pkt_in <= stlv_to_pkt_ack(ack_fifo_dout);
297
 
298
  -- Transmit command response only when the command is completed
299 18 wzab
  -- (to avoid transmiting unstable values, which could e.g. affect
300 15 wzab
  -- packet CRC calculations)
301
  cmd_response_out <= cmd_response_in when r.cmd_ack = r.cmd_run else (others => '0');
302
 
303
  -- Packet descriptors are stored in the desc_memory
304
 
305
  desc_memory_1 : desc_memory
306
    port map (
307
      clk       => clk,
308
      desc_we   => c.desc_we,
309
      desc_addr => to_integer(c.desc_addr),
310
      desc_out  => c.desc_out,
311
      desc_in   => desc_in);
312
 
313
  -- Process used to fill the buffer memory with the data to be transmitted
314
  -- We simply write words to the memory buffer pointed by r.head_ptr
315
  -- When we write the last (0xff-th) word, we signal that the buffer
316 18 wzab
  -- is full.
317
  -- Additionally, when the buffer is partially filled, but the transmission
318
  -- is stopped, we should also signal, that the buffer must be transmitted.
319
  -- However in this case we should also inform the recipient about it.
320
  -- How we can do it?
321 15 wzab
  dta_rcv : process (clk, rst_n)
322
  begin  -- process dta_rcv
323
    if rst_n = '0' then                 -- asynchronous reset (active low)
324 20 wzab
      wrd_addr       <= 0;
325
      dta_buf_flush  <= '0';
326
      dta_buf_full   <= '0';
327
      dmem_we        <= '0';
328
      stored_dta_eod <= '0';
329 15 wzab
    elsif clk'event and clk = '1' then  -- rising clock edge
330
      dmem_we <= '0';
331
      -- if we signalled "data full", we are only waiting for
332
      -- dta_buf_free;
333 20 wzab
      -- However even in this state we must receive the "dta_eod" signal
334 15 wzab
      if dta_buf_full = '1' then
335 20 wzab
        if dta_eod = '1' then
336
          stored_dta_eod <= '1';
337
        end if;
338 15 wzab
        if c.dta_buf_free = '1' then
339 18 wzab
          dta_buf_full  <= '0';
340
          dta_buf_flush <= '0';
341
          wrd_addr      <= 0;
342 15 wzab
        end if;
343
      else
344 18 wzab
        -- end of data is signalled, mark the last buffer as full
345 20 wzab
        if (dta_eod = '1') or (stored_dta_eod = '1') then
346
          -- Clear the stored eod
347
          stored_dta_eod <= '0';
348 18 wzab
          -- In the last word of the packet, write the number of written words
349 20 wzab
          dmem_addr      <= std_logic_vector(r.head_ptr) &
350 43 wzab
                       std_logic_vector(to_unsigned(NWRDS_IN_PKT-1, LOG2_NWRDS_IN_PKT));
351 18 wzab
          dmem_dta      <= std_logic_vector(to_unsigned(wrd_addr, 64));
352
          dmem_we       <= '1';
353
          dta_buf_flush <= '1';
354
          dta_buf_full  <= '1';
355 15 wzab
        -- if data write requested - write it
356 18 wzab
        elsif dta_we = '1' then
357 15 wzab
          dmem_addr <= std_logic_vector(r.head_ptr) &
358
                       std_logic_vector(to_unsigned(wrd_addr, LOG2_NWRDS_IN_PKT));
359
          dmem_we  <= '1';
360
          dmem_dta <= dta;
361
          if wrd_addr < NWRDS_IN_PKT-1 then
362
            wrd_addr <= wrd_addr + 1;
363
          else
364 18 wzab
            dta_buf_flush <= '0';
365
            dta_buf_full  <= '1';
366 15 wzab
          end if;
367
        end if;
368
      end if;
369
    end if;
370
  end process dta_rcv;
371
 
372
 
373
  c1 : process (ack_fifo_empty, ack_pkt_in, cmd_ack, desc_in,
374 18 wzab
                dmgr_state, dta_buf_full, dta_buf_flush, r, snd_ready)
375 15 wzab
  begin  -- process c1
376
    c             <= DESC_MGR_COMB_DEFAULT;  -- set defaults
377
    r_i           <= r;                 -- avoid latches
378
    -- Synchronize command acknowledge lines
379
    r_i.cmd_ack_0 <= cmd_ack;
380
    r_i.cmd_ack   <= r.cmd_ack_0;
381
    if r.retr_delay /= to_unsigned(0, r.retr_delay'length) then
382
      r_i.retr_delay <= r.retr_delay-1;
383
    end if;
384 45 wzab
    dbg             <= x"0";            -- default to avoid latch
385 15 wzab
    dmgr_state_next <= dmgr_state;
386
    -- State machine
387
    case dmgr_state is
388
      when ST_DMGR_RST =>
389
        dbg             <= x"1";
390
        dmgr_state_next <= ST_DMGR_RST1;
391
      when ST_DMGR_RST1 =>
392
        -- We should initialize the 0th position of list descriptors
393
        dbg                  <= x"2";
394
        c.desc_addr          <= r.head_ptr;
395
        c.desc_out           <= desc_in;
396
        c.desc_out.confirmed <= '0';
397
        c.desc_out.valid     <= '0';
398
        c.desc_out.sent      <= '0';
399
        c.desc_out.pkt       <= to_unsigned(0, 32);
400
        c.desc_we            <= '1';
401
        dmgr_state_next      <= ST_DMGR_IDLE;
402
      when ST_DMGR_IDLE =>
403
        dbg <= x"3";
404
        -- First we check, if there are any packets to acknowledge
405
        -- or commands to execute
406
        if ack_fifo_empty = '0' then
407 18 wzab
          if (to_integer(ack_pkt_in.cmd) = FCMD_ACK) or
408
            (to_integer(ack_pkt_in.cmd) = FCMD_NACK) then
409
            -- Prepare for reading of the command.
410
            c.desc_addr     <= ack_pkt_in.pkt(LOG2_N_OF_PKTS-1 downto 0);
411
            dmgr_state_next <= ST_DMGR_ACK1;
412
          else
413
            -- This is a command which requires sending of response.
414
            -- This will be handled by the cmd_proc block (in case
415
            -- of START and STOP it is not the most efficient way,
416
            -- but still sufficient).
417 15 wzab
            -- Always request transmission of result
418
            r_i.cmd_retr <= '1';
419
            -- Check if this is a new command (just checking the sequence number,
420
            -- to avoid more complex logic)
421
            if ack_pkt_in.seq /= r.cmd_seq then
422
              -- If no, store the command and it's argument, and order it to be executed
423
              r_i.cmd_code <= ack_pkt_in.cmd;
424
              r_i.cmd_seq  <= ack_pkt_in.seq;
425
              r_i.cmd_arg  <= ack_pkt_in.pkt;
426
            end if;
427
            c.ack_rd        <= '1';     -- Confirm, that the command was read
428
            dmgr_state_next <= ST_DMGR_CMD;
429
          end if;
430
        elsif dta_buf_full = '1' then
431
          -- We should handle reception of data.
432
          -- If the previously filled buffer is full, pass it for transmission,
433
          -- and allocate the next one.
434
          --
435
          -- Calculate the number of the packet, which shoud be the next "head"
436
          -- packet. We utilize the fact, that calculations are performed modulo
437
          -- N_OF_PKTS (because pointers have length of LOG2_N_OF_PKTS)
438
          r_i.nxt         <= r.head_ptr + 1;
439
          -- Prepare for reading of the current "head" descriptor
440
          c.desc_addr     <= r.head_ptr;
441
          dmgr_state_next <= ST_DMGR_INS1;
442
        elsif (r.tail_ptr /= r.head_ptr) and (r.retr_delay = to_unsigned(0, r.retr_delay'length)) then
443
          -- We need to (re)transmit some buffers
444
          -- prepare reading of the descriptor, which should be transmitted
445
          c.desc_addr     <= r.retr_nxt;
446
          dmgr_state_next <= ST_DMGR_RETR;
447
        elsif r.cmd_retr = '1' and (r.cmd_ack = r.cmd_run) and (r.retr_delay = to_unsigned(0, r.retr_delay'length)) then
448
          -- No data waiting for transmission, and the command response should
449
          -- be transmitted
450
          if snd_ready = '1' then
451
            r_i.retr_delay  <= r.transm_delay;
452
            r_i.cmd_retr    <= '0';
453
            c.snd_cmd_start <= '1';
454
          end if;
455
        end if;
456
      when ST_DMGR_CMD =>
457
        r_i.cmd_run     <= not r.cmd_run;
458
        dmgr_state_next <= ST_DMGR_IDLE;
459
      when ST_DMGR_INS1 =>
460
        dbg <= x"4";
461
        -- First we check, if there is free space, r.nxt is the number of the
462
        -- future head packet.
463
        if (r.nxt = r.tail_ptr) then
464
          -- No free place! The packet, which we would like to fill is still
465
          -- occupied.
466
          -- Return to idle, waiting until something is freed.
467
          -- In this case we should also force retransmission
468
          if r.retr_delay = 0 then
469
            c.desc_addr     <= r.retr_nxt;
470
            dmgr_state_next <= ST_DMGR_RETR;
471
          else
472
            dmgr_state_next <= ST_DMGR_IDLE;
473
          end if;
474
        else
475
          -- We can fill the next buffer
476
          -- First we mark the previous head packet
477
          -- as valid and not confirmed
478 18 wzab
          -- We also set the "flushed" status appropriately
479 15 wzab
          c.desc_addr          <= r.head_ptr;
480
          c.desc_out           <= desc_in;
481
          c.desc_out.confirmed <= '0';
482
          c.desc_out.valid     <= '1';
483 18 wzab
          if dta_buf_flush = '1' then
484
            c.desc_out.flushed <= '1';
485
          else
486
            c.desc_out.flushed <= '0';
487
          end if;
488
          c.desc_we       <= '1';
489 15 wzab
          -- Now we move the "head" pointer
490 18 wzab
          r_i.head_ptr    <= r.nxt;
491 15 wzab
          -- Increase the packet number!
492
          -- We utilize the fact, that packet number automatically
493
          -- wraps to 0 after sending of 2**32 packets!
494 18 wzab
          r_i.cur_pkt     <= r.cur_pkt + 1;
495
          dmgr_state_next <= ST_DMGR_INS2;
496 15 wzab
        end if;
497
      when ST_DMGR_INS2 =>
498
        dbg                  <= x"5";
499
        -- We fill the new head descriptor
500
        c.desc_addr          <= r.head_ptr;
501
        c.desc_out.pkt       <= r.cur_pkt;
502
        c.desc_out.confirmed <= '0';
503
        c.desc_out.valid     <= '0';
504
        c.desc_out.sent      <= '0';
505 18 wzab
        c.desc_out.flushed   <= '0';
506 15 wzab
        c.desc_we            <= '1';
507
        -- Signal, that the buffer is freed
508
        c.dta_buf_free       <= '1';
509
        dmgr_state_next      <= ST_DMGR_IDLE;
510
      when ST_DMGR_ACK1 =>
511
        dbg <= x"6";
512
        -- In this state the desc memory should respond with the data of the
513
        -- buffered packet, so we can state, if this packet is really correctly
514
        -- acknowledged (here we also ignore the NACK packets!
515 18 wzab
        case to_integer(ack_pkt_in.cmd) is
516
          when FCMD_ACK =>
517
            if (ack_pkt_in.pkt = desc_in.pkt) and
518
              (desc_in.valid = '1') then
519
              -- This is really correct, unconfirmed packet
520
              -- Increase the counter of not-repeated ACK packets
521
              -- Write the confirmation
522
              c.desc_addr          <= ack_pkt_in.pkt(LOG2_N_OF_PKTS-1 downto 0);
523
              c.desc_out           <= desc_in;
524
              c.desc_out.valid     <= '0';
525
              c.desc_out.confirmed <= '1';
526
              c.desc_we            <= '1';
527
              -- Here we also handle the case, if the acknowledged packet was
528
              -- the one which is now scheduled for retransmission...
529
              if ack_pkt_in.pkt(LOG2_N_OF_PKTS-1 downto 0) = r.retr_nxt then
530
                r_i.retr_nxt <= r.retr_nxt + 1;
531
              end if;
532
              -- Check, if we need to update the "tail" pointer
533
              if r.tail_ptr = ack_pkt_in.pkt(LOG2_N_OF_PKTS-1 downto 0) then
534
                c.ack_rd        <= '1';
535
                dmgr_state_next <= ST_DMGR_ACK_TAIL;
536
              else
537
                -- If this is not the tail pointer, it means, that some packets
538
                -- or acknowledgements have been lost
539
                -- We trigger retransmission of those packets
540
                r_i.ack_seq     <= ack_pkt_in.seq;
541
                r_i.retr_nxt    <= r.tail_ptr;
542
                -- Set the flag stating that only "earlier"  packets should be retransmitted
543
                r_i.retr_flag   <= '1';
544
                c.ack_rd        <= '1';
545
                dmgr_state_next <= ST_DMGR_IDLE;
546
              end if;
547
            else
548
              -- This packet was already confirmed
549
              -- just flush the ack_fifo
550
              c.ack_rd        <= '1';
551
              dmgr_state_next <= ST_DMGR_IDLE;
552
            end if;
553 43 wzab
          when FCMD_NACK =>
554 18 wzab
            -- This was a NACK command, currently we simply ignore it
555
            -- (later on we will use it to trigger retransmission).
556 15 wzab
            c.ack_rd        <= '1';
557
            dmgr_state_next <= ST_DMGR_IDLE;
558 18 wzab
          when others => null;
559
        end case;
560 15 wzab
      when ST_DMGR_ACK_TAIL =>
561
        dbg             <= x"7";
562
        c.desc_addr     <= r.tail_ptr;
563
        dmgr_state_next <= ST_DMGR_ACK_TAIL_1;
564
      when ST_DMGR_ACK_TAIL_1 =>
565
        dbg <= x"8";
566
        -- In this state we update the "tail" pointer if necessary
567
        if r.tail_ptr /= r.head_ptr then
568
          if desc_in.confirmed = '1' then
569
            r_i.tail_ptr <= r.tail_ptr + 1;  -- it will wrap to 0 automatically!
570
            c.desc_addr  <= r.tail_ptr + 1;
571
          -- We remain in that state, to check the next packet descriptor
572
          else
573
            -- We return to idle
574
            dmgr_state_next <= ST_DMGR_IDLE;
575
          end if;
576
        else
577
          -- Buffer is empty - return to idle
578
          dmgr_state_next <= ST_DMGR_IDLE;
579
        end if;
580
      when ST_DMGR_RETR =>
581
        dbg <= x"9";
582
        -- Here we handle the transmission of a new packet, 
583
        -- retransmission of not confirmed packet
584
        -- We must be sure, that the transmitter is ready
585
        if snd_ready = '0' then
586
          -- transmitter not ready, return to idle
587
          dmgr_state_next <= ST_DMGR_IDLE;
588
        else
589
          -- We will be able to send the next packet, but let's check if
590
          -- this is not the currently filled packet
591
          if r.retr_nxt = r.head_ptr then
592
            -- All packets (re)transmitted, go to the begining of the list
593
            r_i.retr_nxt    <= r.tail_ptr;
594
            -- Clear the flag stating that only packets older than the last
595
            -- acknowledged should be transmitted
596
            r_i.retr_flag   <= '0';
597
            -- and return to idle.
598
            dmgr_state_next <= ST_DMGR_IDLE;
599
          else
600
            -- before jumping to ST_DMGR_RETR, the address bus
601
            -- was set to the address of r.retr_nxt, so now
602
            -- we can read the descriptor, and check if the packet
603
            -- needs to be retransmitted at all...
604
            r_i.pkt      <= desc_in.pkt;
605 18 wzab
            r_i.flushed  <= desc_in.flushed;
606 15 wzab
            r_i.retr_ptr <= r.retr_nxt;
607
            r_i.retr_nxt <= r.retr_nxt + 1;
608
            if desc_in.valid = '1' and desc_in.confirmed = '0' and
609
              ((r.retr_flag = '0') or is_bigger(r.ack_seq, desc_in.seq)) then
610
              if desc_in.sent = '1' then
611
                -- Increase count of retransmitted packets for
612
                -- adaptive adjustment of delay
613
                if r.retr_pkt_count < PKT_CNT_MAX then
614
                  r_i.retr_pkt_count <= r.retr_pkt_count + 1;
615
                end if;
616 26 wzab
                -- Adjust the cumulative retransmission counter
617
                r_i.retr_count <= r.retr_count + 1;
618 15 wzab
              end if;
619
              -- Increase count of all packets for adaptive adjustment
620
              -- of delay
621
              if r.all_pkt_count < PKT_CNT_MAX then
622
                r_i.all_pkt_count <= r.all_pkt_count + 1;
623
              end if;
624
              -- Mark the packet as sent
625
              c.desc_addr     <= r.retr_nxt;
626
              c.desc_out      <= desc_in;
627
              c.desc_out.sent <= '1';
628
              -- increase the sequential number
629
              r_i.seq         <= r.seq + 1;
630
              -- store the packet sequential number
631
              c.desc_out.seq  <= r.seq + 1;
632
              c.desc_we       <= '1';
633
              dmgr_state_next <= ST_DMGR_RETR_2;
634
            else
635
              dmgr_state_next <= ST_DMGR_IDLE;
636
            end if;
637
          end if;
638
        end if;
639
      when ST_DMGR_RETR_2 =>
640
        dbg         <= x"a";
641
        -- In this state, we simply trigger the sender!
642
        c.snd_start <= '1';
643
        if r.cmd_ack = r.cmd_run then
644
          -- command response will be transmitted, so clear the related flag
645
          r_i.cmd_retr <= '0';
646
        end if;
647
        r_i.retr_delay <= r.transm_delay;
648
        -- And we update the delay using the packet statistics
649
        -- You may change the constants used in expressions
650
        -- below to change speed of adjustment
651
        if r.all_pkt_count >= PKT_CNT_MAX then
652 26 wzab
          if r.retr_pkt_count < PKT_CNT_MAX/300 then
653 15 wzab
            if r.transm_delay > 16 then
654
              r_i.transm_delay <= r.transm_delay-r.transm_delay/16;
655
            end if;
656 26 wzab
          elsif r.retr_pkt_count > PKT_CNT_MAX/100 then
657 15 wzab
            if r.transm_delay < 1000000 then
658
              r_i.transm_delay <= r.transm_delay+r.transm_delay/4;
659
            end if;
660
          end if;
661
          r_i.all_pkt_count  <= 0;
662
          r_i.retr_pkt_count <= 0;
663
        end if;
664
        dmgr_state_next <= ST_DMGR_IDLE;
665
      when others => null;
666
    end case;
667
  end process c1;
668
 
669
-- Synchronous process
670
  process (clk, rst_n)
671
  begin  -- process
672
    if rst_n = '0' then                 -- asynchronous reset (active low)
673
      r          <= DESC_MGR_REGS_INI;
674
      dmgr_state <= ST_DMGR_RST;
675
    elsif clk'event and clk = '1' then  -- rising clock edge
676
      r          <= r_i;
677
      dmgr_state <= dmgr_state_next;
678
    end if;
679
  end process;
680
 
681
end dmgr_a1;
682
 
683
 
684
 

powered by: WebSVN 2.1.0

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