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

Subversion Repositories dp_repack_data

[/] [dp_repack_data/] [trunk/] [dp_repack_data.vhd] - Blame information for rev 3

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
--------------------------------------------------------------------------------
2
--
3
-- Copyright (C) 2015
4
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
--
7
-- This program is free software: you can redistribute it and/or modify
8
-- it under the terms of the GNU General Public License as published by
9
-- the Free Software Foundation, either version 3 of the License, or
10
-- (at your option) any later version.
11
--
12
-- This program is distributed in the hope that it will be useful,
13
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
-- GNU General Public License for more details.
16
--
17
-- You should have received a copy of the GNU General Public License
18
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
--
20
--------------------------------------------------------------------------------
21
 
22
-- Purpose:
23
--   The dp_repack_data works both as packer and as unpacker.
24
--
25
-- Block diagram:
26
--
27
-- A) Functional
28
--   The drawing shows g_in_nof_words=4 and g_out_nof_words=2 as example:
29
--
30
--                dp_repack_in               dp_repack_out
31
--                     ___                        ___
32
--                    |   |      pack_sosi       |   |--> src_out
33
--                    | 3 |--------------------->| 1 |
34
--                    |   |                      |   |
35
--                    | 2 | ^                    |   | ^
36
--                    |   | |valid               |   | |shift
37
--                    | 1 | |flush               | 0 | |
38
--                    |   | |                    |   | |
39
--                    | 0 |                      |   |
40
--   snk_in        -->|___|      pack_siso       |___|
41
--   snk_out.ready <--     <---------------------     <-- src_in.ready
42
--   snk_out.xon   <------------------------------------- src_in.xon
43
--
44
--
45
-- B) Flow control
46
--
47
--      RL=1                        RL=1               RL=1
48
--        .                           .                  .
49
--        .        /-----------------------------------------\
50
--        .        |                  .           _____  .   |
51
--        .        |   /------\     nxt_r        |     | r   |
52
--        .        \-->|      |---*-------*----->|p_reg|-----*---> src_out
53
--        .            |      |   |       |      |_____|
54
--     snk_in -------->|p_comb|<--|-------|--------------*-------- src_in
55
--                     |      |   |       |              |
56
--                     |      |   |       v              |
57
--                     |      |   |   /-------\          |
58
--                     |      |   |   |p_flow |          |
59
--                     \------/   |   \-------/          |
60
--                                |       |              |
61
--           nxt_r.hold_out.valid |       |              |
62
--                                v       |              |
63
--                                /|      |r_snk_out     |
64
--                               |0|------/              |
65
--    snk_out <------------------| |                     |
66
--                               |1|---------------------/
67
--                                \|
68
--
69
-- Description:
70
--   The dp_repack_data repacks g_in_nof_words of width g_in_dat_w into
71
--   g_out_nof_words of width g_out_dat_w.
72
--
73
-- . g_in_bypass, g_out_bypass
74
--   The dp_repack_in and dp_repack_out can be bypassed to save logic and to
75
--   avoid the pipeline stage. Default both are FALSE, but they can be set
76
--   TRUE if:
77
--
78
--   . g_in_bypass =TRUE if g_in_nof_words=g_out_nof_words or g_in_nof_words=1
79
--   . g_out_bypass=TRUE if g_in_nof_words=g_out_nof_words or g_out_nof_words=1
80
--
81
--   Both the dp_repack_in and dp_repack_out stage do work correctly independent
82
--   of the g_*_bypass setting. When g_*_bypass=FALSE then they merely
83
--   add a transparant pipeline delay. It is important that they also work for
84
--   g_*_bypass=FALSE because that gives confidence that their implementation
85
--   structure is ok.
86
--
87
-- . g_in_nof_words and input block size
88
--   The input block size in words is indicated by snk_in.sop and snk_in.eop.
89
--   Each subsection of g_in_nof_words is packed into g_out_nof_words. The
90
--   input block size does not have to be a multiple of g_in_nof_words. When
91
--   the snk_in.eop occurs the last repack is initiated without need for input
92
--   data padding. If the block length is an integer multiple of
93
--   g_in_nof_words then the dp_repack_data introduces no gaps between blocks.
94
--   If the block length is a fractional multiple of g_in_nof_words then there
95
--   will be a gap after the block due to that the dp_repack_in needs to
96
--   shift up the last subsection for the 'missing' input words.
97
--
98
-- . g_in_dat_w*g_in_nof_words <, =, > g_in_dat_w*g_in_nof_words
99
--   . = : no subsection zero padding
100
--   . < : the subsections will be zero padded
101
--   . > : then the input must have sufficient zero padded bits per
102
--         subsection that can be stripped without data loss.
103
--
104
-- . Resolution of the empty field
105
--   The g_in_symbol_w is used to define the resolution of snk_in.empty and
106
--   the g_out_symbol_w is used to define the resolution of src_out.empty. If
107
--   they are 1 then the resolution is in number of bits, because the symbol
108
--   size is then 1 bit. Their value has no effect on the packed data it self,
109
--   only on the meaning of the empty field. Hence if the empty field is not
110
--   used, then the setting of g_in_symbol_w and g_out_symbol_w is dont care.
111
--
112
-- Remarks:
113
-- . Originally reused from LOFAR rad_repack.vhd and rad_repack(rtl).vhd. This
114
--   dp_repack_data still uses the shift in input register in and the shift out
115
--   output register, but no longer the intermediate buffer register.
116
--   Using shift in and shift out may ease timing closure because the routing
117
--   is more local compared to using a demultiplexer to put the input data in
118
--   the input register and a multiplexer to get the data directly from the
119
--   output register. For the demultiplexer / multiplexer it would be possible
120
--   to only use one internal register.
121
--   Using shift up is sufficient, the shift down option is not needed. With
122
--   shift up the data is input a [0] and output the high index.
123
--   Instead of requiring an snk_in.valid duty cycle this dp_repack_data uses
124
--   snk_out.ready flow control and can handle src_in.ready flow control.
125
--
126
-- . To pack ETH/IP/UDP header slv of 14 + 20 + 8 = 42 octets into 32 bit words
127
--   use:
128
--     u_dp_repack_data : ENTITY .dp_repack_data
129
--     GENERIC MAP (
130
--       g_in_bypass         => TRUE,
131
--       g_in_dat_w          => 8 * 42,
132
--       g_in_nof_words      => 1,
133
--       g_in_symbol_w       => 8,
134
--       g_out_bypass        => FALSE,
135
--       g_out_dat_w         => 32,
136
--       g_out_nof_words     => 11,
137
--       g_out_symbol_w      => 8
138
--     )
139
--   The src_out.empty will be 2, because:
140
--     (g_out_dat_w*g_out_nof_words-g_in_dat_w*g_in_nof_words)/g_out_symbol_w
141
--      = (32*11 - 42*8*1)/ 8 = 2 octet symbols
142
--       
143
-- Design steps:
144
-- * In total the development took 5 days. On day 3 I was in distress because
145
--   I could not get it to work so I needed to rethink. After changing to the
146
--   new flow control scheme that uses nxt_r the design was gradually improved
147
--   by getting the dp_repack_data instances in tb_tb_dp_repack_data to work one
148
--   by one. First only for e_active stimuli and later also for e_random and
149
--   e_pulse. Initially about 80 % of the functionality was implemented but
150
--   and subsequently each feature was verified starting with the basic 
151
--   features and then themore detailed features. This step by step approach
152
--   makes that the bugs appear one by one instead of all together. Without a
153
--   step by step approach the bugs are too big to solve.
154
--   . First cases with g_in_nof_words=1 and g_out_nof_words were made to work
155
--     for different g_pkt_len <, =, > g_in_nof_words.
156
--   . Then the empty functionality for g_pkt_len MOD g_in_nof_words /= 0 was
157
--     added.
158
--   . Tried g_out_dat_w=1 which makes dp_repack_data a serializer/deserializer.
159
--   . Then apply external flow control using c_dp_flow_control_enum_arr in
160
--     the tb_tb_dp_repack_data was verified resulting in small corrections.
161
--   . Then verified g_in_dat_w * g_in_nof_words > or < g_out_dat_w *
162
--     g_out_nof_words which require padding in the subsection. The > case
163
--     occurs for packing and the < case then occurs for unpacking.
164
--   . Added g_bypass to force using wires instead of a void dp_repack_in or
165
--     dp_repack_out stage.
166
--   . Verified g_in_symbol_w and g_out_symbol_w /= 1.
167
-- * The development used the tb_dp_repack_data testbench that does a pack and
168
--   an unpack to be able to verify the data. The c_no_unpack and
169
--   c_enable_repack_in and c_enable_repack_out parameters in the tb are
170
--   useful to be able to isolate a component for debugging.
171
 
172
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib;
173
USE IEEE.std_logic_1164.ALL;
174
USE common_pkg_lib.common_pkg.ALL;
175
USE dp_pkg_lib.dp_stream_pkg.ALL;
176
 
177
ENTITY dp_repack_in IS
178
  GENERIC (
179
    g_bypass          : BOOLEAN := FALSE;
180
    g_in_dat_w        : NATURAL;
181
    g_in_nof_words    : NATURAL;
182
    g_in_symbol_w     : NATURAL := 1  -- default 1 for snk_in.empty in nof bits, else use power of 2
183
  );
184
  PORT (
185
    rst              : IN  STD_LOGIC;
186
    clk              : IN  STD_LOGIC;
187
 
188
    snk_out          : OUT t_dp_siso;
189
    snk_in           : IN  t_dp_sosi;
190
 
191
    src_in           : IN  t_dp_siso;
192
    src_out          : OUT t_dp_sosi
193
  );
194
END dp_repack_in;
195
 
196
 
197
ARCHITECTURE rtl OF dp_repack_in IS
198
 
199
  CONSTANT c_in_buf_dat_w      : NATURAL := g_in_dat_w * g_in_nof_words;
200
  CONSTANT c_bit_cnt_max       : NATURAL := c_in_buf_dat_w;
201
  CONSTANT c_in_empty_lo       : NATURAL := true_log2(g_in_symbol_w);
202
 
203
  TYPE t_dat_arr  IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
204
 
205
  TYPE t_reg IS RECORD
206
    dat_arr       : t_dat_arr(g_in_nof_words-1 DOWNTO 0);     -- internally use dat_arr[] to represent v.src_out.data
207
    src_out       : t_dp_sosi;                                -- sosi output
208
    hold_out      : t_dp_sosi;                                -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until src_in.ready
209
    flush         : STD_LOGIC;                                -- shift when snk_in.valid or flush in case the last subsection has < g_in_nof_words
210
    dat_bit_cnt   : NATURAL RANGE 0 TO c_bit_cnt_max;         -- actual nof bits in subsection
211
    pack_bit_cnt  : NATURAL RANGE 0 TO c_bit_cnt_max;         -- count nof bits in subsection
212
  END RECORD;
213
 
214
  SIGNAL data_vec   : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0);
215
 
216
  SIGNAL r_snk_out  : t_dp_siso := c_dp_siso_rdy;
217
  SIGNAL r          : t_reg;
218
  SIGNAL nxt_r      : t_reg;
219
 
220
  -- Debug signals
221
  SIGNAL snk_in_data        : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
222
  SIGNAL i_src_out          : t_dp_sosi;
223
  SIGNAL src_out_data       : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0);
224
 
225
  SIGNAL dbg_g_in_dat_w   : NATURAL := g_in_dat_w;
226
  SIGNAL dbg_in_nof_words : NATURAL := g_in_nof_words;
227
  SIGNAL dbg_in_symbol_w  : NATURAL := g_in_symbol_w;
228
  SIGNAL dbc_in_buf_dat_w : NATURAL := c_in_buf_dat_w;
229
 
230
BEGIN
231
 
232
  snk_in_data <= snk_in.data(g_in_dat_w-1 DOWNTO 0);
233
 
234
  src_out      <= i_src_out;
235
  src_out_data <= i_src_out.data(c_in_buf_dat_w-1 DOWNTO 0);
236
 
237
  gen_bypass : IF g_bypass=TRUE GENERATE
238
    snk_out   <= src_in;
239
    i_src_out <= snk_in;
240
  END GENERATE;
241
 
242
  no_bypass : IF g_bypass=FALSE GENERATE
243
 
244
    p_comb : PROCESS(rst, r, snk_in, data_vec, src_in)
245
      VARIABLE v : t_reg;
246
    BEGIN
247
      ------------------------------------------------------------------------
248
      -- Default
249
      v := r;
250
      v.src_out.sync  := '0';
251
      v.src_out.valid := '0';
252
      v.src_out.sop   := '0';
253
      v.src_out.eop   := '0';
254
 
255
      --------------------------------------------------------------------------
256
      -- Function
257
      IF r.hold_out.valid='0' THEN
258
 
259
        -- Clear hold_out for new output valid (= new subsection)
260
        IF r.src_out.valid='1' THEN
261
          v.hold_out := c_dp_sosi_rst;
262
        END IF;
263
 
264
        -- Capture the snk_in block info that is valid at sop and eop
265
        IF snk_in.sop='1' THEN
266
          v.hold_out.sop    := '1';
267
          v.hold_out.sync   := snk_in.sync;
268
          v.src_out.bsn     := snk_in.bsn;
269
          v.src_out.channel := snk_in.channel;
270
        END IF;
271
        IF snk_in.eop='1' THEN
272
          v.hold_out.eop    := '1';
273
          v.hold_out.empty  := SHIFT_UVEC(snk_in.empty, -c_in_empty_lo);  -- use snk_in.empty as offset for src_out.empty in nof bits
274
          v.src_out.err     := snk_in.err;
275
        END IF;
276
 
277
        -- Capture the data per subsection in a block
278
        IF snk_in.valid='1' OR r.flush='1' THEN
279
          -- shift in during block
280
          v.dat_arr(g_in_nof_words-1 DOWNTO 1) := r.dat_arr(g_in_nof_words-2 DOWNTO 0);  -- shift up from low to high and shift in at index 0
281
          IF r.flush='1' THEN
282
            v.dat_arr(0) := (OTHERS=>'0');                                               -- shift in data=0 for flush
283
          ELSE
284
            v.dat_arr(0) := snk_in.data(g_in_dat_w-1 DOWNTO 0);                          -- shift in valid data
285
          END IF;
286
 
287
          -- pack subsection
288
          IF r.pack_bit_cnt<c_in_buf_dat_w-g_in_dat_w THEN
289
            v.pack_bit_cnt := r.pack_bit_cnt + g_in_dat_w;
290
 
291
            -- early end of pack subsection
292
            IF snk_in.eop='1' THEN
293
              v.flush := '1';                   -- enable flush in case eop occurs before end of pack subsection
294
              v.dat_bit_cnt := v.pack_bit_cnt;  -- capture the current subsection pack_bit_cnt
295
            END IF;
296
          ELSE                                  -- r.pack_bit_cnt=c_in_buf_dat_w-g_in_dat_w
297
            -- default end of pack subsection
298
            v.pack_bit_cnt := 0;
299
            v.flush := '0';
300
            IF r.flush='0' THEN
301
              v.dat_bit_cnt := c_in_buf_dat_w;  -- set default subsection pack_bit_cnt
302
            END IF;
303
 
304
            v.hold_out.valid := '1';            -- the function has new data to output
305
          END IF;
306
        END IF;
307
 
308
        -- pass on the v.dat_arr as data vector
309
        v.src_out.data := RESIZE_DP_DATA(data_vec);
310
 
311
        -- pass on dat_bit_cnt via DP empty field
312
        v.src_out.empty := INCR_UVEC(v.hold_out.empty, c_in_buf_dat_w - v.dat_bit_cnt);
313
 
314
        -- output input stage into output stage when ready, else hold_out.valid to signal pending output
315
        IF v.hold_out.valid='1' THEN
316
          IF src_in.ready='1' THEN
317
            v.src_out.valid := '1';
318
            v.src_out.sync  := v.hold_out.sync;
319
            v.src_out.sop   := v.hold_out.sop;
320
            v.src_out.eop   := v.hold_out.eop;
321
            v.hold_out.valid := '0';
322
          END IF;
323
        END IF;
324
      ELSE
325
        -- pending output
326
        IF src_in.ready='1' THEN
327
          v.src_out.valid := '1';
328
          v.src_out.sync  := r.hold_out.sync;
329
          v.src_out.sop   := r.hold_out.sop;
330
          v.src_out.eop   := r.hold_out.eop;
331
          v.hold_out.valid := '0';
332
        END IF;
333
      END IF;
334
 
335
      ------------------------------------------------------------------------
336
      -- Reset and nxt_r
337
      IF rst = '1' THEN
338
        v.src_out       := c_dp_sosi_rst;
339
        v.hold_out      := c_dp_sosi_rst;
340
        v.flush         := '0';
341
        v.dat_bit_cnt   := 0;
342
        v.pack_bit_cnt  := 0;
343
      END IF;
344
 
345
      nxt_r <= v;
346
    END PROCESS;
347
 
348
    --------------------------------------------------------------------------
349
    -- p_reg
350
    r <= nxt_r WHEN rising_edge(clk);
351
 
352
    --------------------------------------------------------------------------
353
    -- Wires
354
    p_data_vec : PROCESS(nxt_r)
355
    BEGIN
356
      FOR I IN 0 TO g_in_nof_words-1 LOOP
357
        data_vec((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= nxt_r.dat_arr(I);
358
      END LOOP;
359
    END PROCESS;
360
 
361
    --------------------------------------------------------------------------
362
    -- Wired output
363
    i_src_out <= r.src_out;
364
 
365
    --------------------------------------------------------------------------
366
    -- Flow control
367
 
368
    -- local function flow control
369
    p_flow : PROCESS(nxt_r)
370
    BEGIN
371
      r_snk_out <= c_dp_siso_rdy;
372
      IF nxt_r.flush='1' THEN
373
        r_snk_out.ready <= '0';   -- input shift in stage function is always ready except when flushing
374
      END IF;
375
    END PROCESS;
376
 
377
    -- combined local and remote src_in flow control
378
    snk_out.ready <= r_snk_out.ready WHEN nxt_r.hold_out.valid='0' ELSE src_in.ready;  -- if there is pending output then the src_in ready determines the flow control
379
    snk_out.xon   <= src_in.xon;  -- just pass on the xon/off frame flow control
380
 
381
  END GENERATE;
382
 
383
END rtl;
384
 
385
 
386
 
387
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib;
388
USE IEEE.std_logic_1164.ALL;
389
USE common_pkg_lib.common_pkg.ALL;
390
USE dp_pkg_lib.dp_stream_pkg.ALL;
391
 
392
ENTITY dp_repack_out IS
393
  GENERIC (
394
    g_bypass           : BOOLEAN := FALSE;
395
    g_in_buf_dat_w     : NATURAL;
396
    g_out_dat_w        : NATURAL;
397
    g_out_nof_words    : NATURAL;
398
    g_out_symbol_w     : NATURAL := 1  -- default 1 for snk_in.empty in nof bits, else use power of 2
399
  );
400
  PORT (
401
    rst              : IN  STD_LOGIC;
402
    clk              : IN  STD_LOGIC;
403
 
404
    snk_out          : OUT t_dp_siso;
405
    snk_in           : IN  t_dp_sosi;
406
 
407
    src_in           : IN  t_dp_siso;
408
    src_out          : OUT t_dp_sosi
409
  );
410
END dp_repack_out;
411
 
412
ARCHITECTURE rtl OF dp_repack_out IS
413
 
414
  CONSTANT c_out_buf_dat_w     : NATURAL := g_out_dat_w * g_out_nof_words;
415
  CONSTANT c_out_buf_dat_lo    : NATURAL := sel_a_b(c_out_buf_dat_w > g_in_buf_dat_w, c_out_buf_dat_w -  g_in_buf_dat_w, 0);  -- pack into subsection with 0 or more padding bits
416
  CONSTANT c_snk_in_dat_lo     : NATURAL := sel_a_b(c_out_buf_dat_w < g_in_buf_dat_w,  g_in_buf_dat_w - c_out_buf_dat_w, 0);  -- unpack from subsection that has 0 or more padding bits
417
  CONSTANT c_bit_cnt_max       : NATURAL := c_out_buf_dat_w;
418
  CONSTANT c_out_empty_lo      : NATURAL := true_log2(g_out_symbol_w);
419
 
420
  TYPE t_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
421
 
422
  TYPE t_reg IS RECORD
423
    dat_arr       : t_dat_arr(g_out_nof_words-1 DOWNTO 0);
424
    src_out       : t_dp_sosi;
425
    hold_out      : t_dp_sosi;                                -- hold src_out valid and sync/sop/eop until src_in.ready
426
    shift         : STD_LOGIC;                                -- shift out the dat_arr
427
    dat_bit_cnt   : NATURAL RANGE 0 TO c_bit_cnt_max;         -- actual nof bits in subsection
428
    pack_bit_cnt  : NATURAL RANGE 0 TO c_bit_cnt_max;         -- count nof bits in subsection
429
    empty_bit_cnt : NATURAL RANGE 0 TO c_bit_cnt_max;         -- empty nof bits in subsection
430
    eos           : STD_LOGIC;                                -- end of subsection
431
  END RECORD;
432
 
433
  SIGNAL data_vec  : STD_LOGIC_VECTOR(c_out_buf_dat_w-1 DOWNTO 0) := (OTHERS=>'0');
434
 
435
  SIGNAL r_snk_out : t_dp_siso := c_dp_siso_rdy;
436
  SIGNAL r         : t_reg;
437
  SIGNAL nxt_r     : t_reg;
438
 
439
  -- Debug signals
440
  SIGNAL snk_in_data        : STD_LOGIC_VECTOR(g_in_buf_dat_w-1 DOWNTO 0);
441
  SIGNAL i_src_out          : t_dp_sosi;
442
  SIGNAL src_out_data       : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
443
 
444
  SIGNAL dbg_g_in_buf_dat_w : NATURAL := g_in_buf_dat_w;
445
  SIGNAL dbg_g_out_dat_w    : NATURAL := g_out_dat_w;
446
  SIGNAL dbg_out_nof_words  : NATURAL := g_out_nof_words;
447
  SIGNAL dbg_out_symbol_w   : NATURAL := g_out_symbol_w;
448
  SIGNAL dbc_out_buf_dat_w  : NATURAL := c_out_buf_dat_w;
449
  SIGNAL dbc_out_buf_dat_lo : NATURAL := c_out_buf_dat_lo;
450
  SIGNAL dbc_snk_in_dat_lo  : NATURAL := c_snk_in_dat_lo;
451
 
452
BEGIN
453
 
454
  snk_in_data <= snk_in.data(g_in_buf_dat_w-1 DOWNTO 0);
455
 
456
  src_out      <= i_src_out;
457
  src_out_data <= i_src_out.data(g_out_dat_w-1 DOWNTO 0);
458
 
459
  gen_bypass : IF g_bypass=TRUE GENERATE
460
    snk_out <= src_in;
461
 
462
    p_src_out : PROCESS(snk_in)
463
    BEGIN
464
      i_src_out <= snk_in;
465
      IF c_snk_in_dat_lo>0 THEN
466
        i_src_out.data  <= SHIFT_UVEC(snk_in.data,   c_snk_in_dat_lo);
467
        i_src_out.empty <= INCR_UVEC( snk_in.empty, -c_snk_in_dat_lo);
468
      END IF;
469
      IF c_out_buf_dat_lo>0 THEN
470
        i_src_out.data  <= SHIFT_UVEC(snk_in.data, -c_out_buf_dat_lo);
471
        i_src_out.empty <= INCR_UVEC( snk_in.empty, c_out_buf_dat_lo);
472
      END IF;
473
    END PROCESS;
474
  END GENERATE;
475
 
476
  no_bypass : IF g_bypass=FALSE GENERATE
477
 
478
    p_comb : PROCESS(rst, snk_in, r, data_vec, src_in)
479
      VARIABLE v : t_reg;
480
    BEGIN
481
      ------------------------------------------------------------------------
482
      -- Default
483
      v := r;
484
      v.src_out.sync  := '0';
485
      v.src_out.valid := '0';
486
      v.src_out.sop   := '0';
487
      v.src_out.eop   := '0';
488
 
489
      ------------------------------------------------------------------------
490
      -- Function
491
      IF r.hold_out.valid='0' THEN
492
 
493
        -- Clear hold_out for new output valid
494
        IF r.src_out.sop='1' THEN
495
          v.hold_out.sync := '0';
496
          v.hold_out.sop  := '0';
497
        END IF;
498
        IF r.src_out.eop='1' THEN
499
          v.hold_out.eop := '0';
500
        END IF;
501
 
502
        -- Capture the snk_in block info that is valid at sop and eop
503
        IF snk_in.sop='1' THEN
504
          v.hold_out.sop    := '1';
505
          v.hold_out.sync   := snk_in.sync;
506
          v.src_out.bsn     := snk_in.bsn;
507
          v.src_out.channel := snk_in.channel;
508
        END IF;
509
        IF snk_in.eop='1' THEN
510
          v.hold_out.eop    := '1';  -- local function will calculate src_out.empty based on snk_in.empty
511
          v.src_out.err     := snk_in.err;
512
        END IF;
513
 
514
        IF r.shift='1' THEN
515
          -- shift out rest of subsection
516
          v.hold_out.valid := '1';
517
 
518
          v.dat_arr(g_out_nof_words-1 DOWNTO 1) := r.dat_arr(g_out_nof_words-2 DOWNTO 0);  -- shift up from low to high and shift out at high index
519
          v.dat_arr(0) := (OTHERS=>'0');                                                   -- shift in data=0
520
 
521
          v.pack_bit_cnt := r.pack_bit_cnt - g_out_dat_w;
522
 
523
          -- end of pack subsection
524
          IF v.pack_bit_cnt<=r.empty_bit_cnt THEN
525
            v.eos   := '1';                     -- end of subsection, so ready for new snk_in
526
            v.shift := '0';                     -- stop shifting
527
          END IF;
528
 
529
        ELSIF snk_in.valid='1' THEN
530
          -- start of pack subsection
531
          v.hold_out.valid := '1';
532
 
533
          FOR I IN 0 TO g_out_nof_words-1 LOOP
534
            v.dat_arr(I) := data_vec((I+1)*g_out_dat_w-1 DOWNTO I*g_out_dat_w);
535
          END LOOP;
536
 
537
          v.dat_bit_cnt := g_in_buf_dat_w - c_snk_in_dat_lo;          -- default dat_bit_cnt per subsection
538
          IF snk_in.eop='1' THEN
539
            v.dat_bit_cnt := g_in_buf_dat_w - TO_UINT(snk_in.empty);  -- pass on last subsection dat_bit_cnt info via DP empty field
540
          END IF;
541
 
542
          v.pack_bit_cnt  := c_out_buf_dat_w - g_out_dat_w;
543
          v.empty_bit_cnt := c_out_buf_dat_w - v.dat_bit_cnt;
544
          v.eos           := '0';
545
          v.shift         := '1';
546
 
547
          -- end of pack subsection
548
          IF v.pack_bit_cnt<=v.empty_bit_cnt THEN
549
            v.eos   := '1';         -- end of subsection, so ready for new snk_in
550
            v.shift := '0';
551
          END IF;
552
        END IF;
553
 
554
        -- fill in local empty if this is the last subsection of a block
555
        IF v.eos='1' THEN
556
          IF v.hold_out.eop='1' THEN
557
            v.src_out.empty := TO_DP_EMPTY(v.empty_bit_cnt - v.pack_bit_cnt);  -- in nof bits
558
            v.src_out.empty := SHIFT_UVEC(v.src_out.empty, c_out_empty_lo);    -- in nof symbols
559
          END IF;
560
        END IF;
561
 
562
        -- pass on the v.dat_arr as data vector
563
        v.src_out.data  := RESIZE_DP_DATA(v.dat_arr(g_out_nof_words-1));
564
 
565
        -- output valid data when ready, else hold_out.valid to signal pending output
566
        IF v.hold_out.valid='1' THEN
567
          IF src_in.ready='1' THEN
568
            v.src_out.valid  := '1';
569
            v.src_out.sync   := v.hold_out.sync;
570
            v.src_out.sop    := v.hold_out.sop;
571
            v.src_out.eop    := v.hold_out.eop AND v.eos;  -- output eop at end of subsection
572
            v.hold_out.valid := '0';
573
          END IF;
574
        END IF;
575
 
576
      ELSE
577
        -- pending output
578
        IF src_in.ready='1' THEN
579
          v.src_out.valid := '1';
580
          v.src_out.sync  := r.hold_out.sync;
581
          v.src_out.sop   := r.hold_out.sop;
582
          v.src_out.eop   := r.hold_out.eop AND r.eos;  -- output eop at end of subsection
583
          v.hold_out.valid := '0';
584
        END IF;
585
      END IF;
586
 
587
      ------------------------------------------------------------------------
588
      -- Reset and nxt_r
589
      IF rst = '1' THEN
590
        v.src_out       := c_dp_sosi_rst;
591
        v.hold_out      := c_dp_sosi_rst;
592
        v.shift         := '0';
593
        v.dat_bit_cnt   := 0;
594
        v.pack_bit_cnt  := 0;
595
        v.empty_bit_cnt := 0;
596
        v.eos           := '0';
597
      END IF;
598
 
599
      nxt_r <= v;
600
    END PROCESS;
601
 
602
    --------------------------------------------------------------------------
603
    -- p_reg
604
    r <= nxt_r WHEN rising_edge(clk);
605
 
606
    --------------------------------------------------------------------------
607
    -- Wires
608
    data_vec(c_out_buf_dat_w-1 DOWNTO c_out_buf_dat_lo) <= snk_in.data(g_in_buf_dat_w-1 DOWNTO c_snk_in_dat_lo);
609
 
610
    --------------------------------------------------------------------------
611
    -- Wired output
612
    i_src_out <= r.src_out;
613
 
614
    --------------------------------------------------------------------------
615
    -- Flow control
616
 
617
    -- local function flow control
618
    p_flow : PROCESS(nxt_r)
619
    BEGIN
620
      r_snk_out <= c_dp_siso_rdy;
621
      IF nxt_r.shift='1' AND nxt_r.eos='0' THEN
622
        r_snk_out.ready <= '0';   -- output shift out stage function is only ready when it is not shifting or at the end of the subsection
623
      END IF;
624
    END PROCESS;
625
 
626
    -- combined local and remote src_in flow control
627
    snk_out.ready <= r_snk_out.ready WHEN nxt_r.hold_out.valid='0' ELSE src_in.ready;  -- if there is pending output then the src_in ready determines the flow control
628
    snk_out.xon   <= src_in.xon;  -- just pass on the xon/off frame flow control
629
 
630
  END GENERATE;
631
 
632
END rtl;
633
 
634
 
635
 
636
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib;
637
USE IEEE.std_logic_1164.ALL;
638
USE common_pkg_lib.common_pkg.ALL;
639
USE dp_pkg_lib.dp_stream_pkg.ALL;
640
 
641
ENTITY dp_repack_data IS
642
  GENERIC (
643
    g_enable_repack_in  : BOOLEAN := TRUE;
644
    g_enable_repack_out : BOOLEAN := TRUE;
645
    g_in_bypass         : BOOLEAN := FALSE;
646
    g_in_dat_w          : NATURAL;
647
    g_in_nof_words      : NATURAL;
648
    g_in_symbol_w       : NATURAL := 1;  -- default 1 for snk_in.empty in nof bits, else use power of 2
649
    g_out_bypass        : BOOLEAN := FALSE;
650
    g_out_dat_w         : NATURAL;
651
    g_out_nof_words     : NATURAL;
652
    g_out_symbol_w      : NATURAL := 1   -- default 1 for src_out.empty in nof bits, else use power of 2
653
  );
654
  PORT (
655
    rst              : IN  STD_LOGIC;
656
    clk              : IN  STD_LOGIC;
657
 
658
    snk_out          : OUT t_dp_siso;
659
    snk_in           : IN  t_dp_sosi;
660
 
661 3 danv
    src_in           : IN  t_dp_siso := c_dp_siso_rdy;
662 2 danv
    src_out          : OUT t_dp_sosi
663
  );
664
END dp_repack_data;
665
 
666
 
667
ARCHITECTURE str OF dp_repack_data IS
668
 
669
  CONSTANT c_in_buf_dat_w      : NATURAL := g_in_dat_w * g_in_nof_words;
670
 
671
  SIGNAL snk_in_data       : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
672
  SIGNAL i_snk_out         : t_dp_siso;
673
 
674
  SIGNAL pack_siso         : t_dp_siso;
675
  SIGNAL pack_sosi         : t_dp_sosi;
676
  SIGNAL pack_sosi_data    : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0);
677
 
678
  SIGNAL i_src_out         : t_dp_sosi;
679
  SIGNAL src_out_data      : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
680
 
681
  SIGNAL snk_out_ready_reg : STD_LOGIC_VECTOR(0 TO c_dp_stream_rl);
682
  SIGNAL pack_ready_reg    : STD_LOGIC_VECTOR(0 TO c_dp_stream_rl);
683
 
684
BEGIN
685
 
686
  snk_out <= i_snk_out;
687
  src_out <= i_src_out;
688
 
689
  snk_in_data    <= snk_in.data(g_in_dat_w-1 DOWNTO 0);
690
  pack_sosi_data <= pack_sosi.data(c_in_buf_dat_w-1 DOWNTO 0);
691
  src_out_data   <= i_src_out.data(g_out_dat_w-1 DOWNTO 0);
692
 
693
  no_dp_repack_in : IF g_enable_repack_in=FALSE GENERATE
694
    i_snk_out <= pack_siso;
695
    pack_sosi <= snk_in;
696
  END GENERATE;
697
 
698
  gen_dp_repack_in : IF g_enable_repack_in=TRUE GENERATE
699
    u_dp_repack_in : ENTITY work.dp_repack_in
700
    GENERIC MAP (
701
      g_bypass       => g_in_bypass,
702
      g_in_dat_w     => g_in_dat_w,
703
      g_in_nof_words => g_in_nof_words,
704
      g_in_symbol_w  => g_in_symbol_w
705
    )
706
    PORT MAP (
707
      rst      => rst,
708
      clk      => clk,
709
 
710
      snk_out  => i_snk_out,
711
      snk_in   => snk_in,
712
 
713
      src_in   => pack_siso,
714
      src_out  => pack_sosi
715
    );
716
  END GENERATE;
717
 
718
  no_dp_repack_out : IF g_enable_repack_out=FALSE GENERATE
719
    pack_siso <= src_in;
720
    i_src_out <= pack_sosi;
721
  END GENERATE;
722
 
723
  gen_dp_repack_out : IF g_enable_repack_out=TRUE GENERATE
724
    u_dp_repack_out : ENTITY work.dp_repack_out
725
    GENERIC MAP (
726
      g_bypass        => g_out_bypass,
727
      g_in_buf_dat_w  => c_in_buf_dat_w,
728
      g_out_dat_w     => g_out_dat_w,
729
      g_out_nof_words => g_out_nof_words,
730
      g_out_symbol_w  => g_out_symbol_w
731
    )
732
    PORT MAP (
733
      rst      => rst,
734
      clk      => clk,
735
 
736
      snk_out  => pack_siso,
737
      snk_in   => pack_sosi,
738
 
739
      src_in   => src_in,
740
      src_out  => i_src_out
741
    );
742
  END GENERATE;
743
 
744
  -- Simulation only: internal stream RL verification
745
  proc_dp_siso_alert(clk, snk_in, i_snk_out, snk_out_ready_reg);
746
  proc_dp_siso_alert(clk, pack_sosi, pack_siso, pack_ready_reg);
747
 
748
END str;

powered by: WebSVN 2.1.0

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