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 5

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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