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

Subversion Repositories astron_wpfb

[/] [astron_wpfb/] [trunk/] [dp_block_gen_valid_arr.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3
-- Copyright (C) 2011
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 : Generate the sosi control for a block of data based on the
23
--           input valid
24
-- Description:
25
--   All input streams in the snk_in_arr must have the same sosi ctrl and info
26
--   fields, such that the valid from snk_in_arr(0) is sufficient. Only the
27
--   data, re, im in the snk_in_arr() differs. Therefore default connect snk_in
28
--   = snk_in_arr(0).
29
-- 
30
--   When enabled (enable='1') then a block of g_nof_data_per_block words is
31
--   output via src_out_arr under flow control by the input valid.
32
--
33
--   The input sync, sop and eop are ignored. For the output the sync, sop and 
34
--   eop are generated by counting the input valid and using
35
--   g_nof_data_per_block for the output sop and eop, and using
36
--   g_nof_blk_per_sync for the output sync.
37
--
38
--   The first active input valid starts the dp_block_gen_valid_arr. The first
39
--   output block will have an output sync and every g_nof_blk_per_sync there
40
--   is another output sync. Each output block is marked by output sop and
41
--   output eop. The output sop also marks the output BSN. The output BSN is
42
--   generated such that it increments for every block and that it restarts at
43
--   0 at every output sync.
44
--
45
--   Typically the size of g_nof_blk_per_sync*g_nof_data_per_block should match
46
--   the number of input valids in an input sync interval.
47
--
48
--   The local BSN restarts at 0 for every new output sync interval, but instead
49
--   of BSN = 0 the input BSN will be inserted at the first block in a new
50
--   output sync interval. If the first output BSN should remain 0 then simply
51
--   keep snk_in.bsn = 0.
52
--
53
--   g_nof_pages_bsn:
54
--   The input BSN is not available in snk_in_arr(0) if the upstream component
55
--   does not pass the BSN on. In that case the snk_in.sync and snk_in.bsn can
56
--   be connected to some further upstream interface that does have the proper
57
--   BSN. The input BSN is then buffered to align it with the local sync that is 
58
--   recreated for the output. This buffer is set via g_nof_pages_bsn. Typically
59
--   g_nof_pages_bsn = 1 is sufficient to align the BSN along some DSP,
60
--   components, because the latency in number of blocks of most DSP functions
61
--   is much less than a sync interval. For a corner turn that operates per sync
62
--   interval choosing g_nof_pages_bsn = 2 seems appropriate.
63
--
64
--   g_check_input_sync:
65
--   When g_check_input_sync=FALSE then the input sync is ignored and the first
66
--   input valid that occurs after when enable is active will start the local
67
--   sync. When g_check_input_sync=TRUE then the block output for a new sync
68
--   interval is only started if the input valid also coincides with a input
69
--   sync. Until then all input valid are ignored and there is no output then.
70
-- 
71
-- Usage:
72
-- * Example 1: Use snk_in.valid to recreate sync, sop, eop, bsn for a DP
73
--              function that only passes on the valid.
74
--
75
--   - g_check_input_sync = False
76
--   - g_nof_pages_bsn    = 0
77
--   
78
--                                           |------|
79
--               snk_in_arr() ----*--------->|      |----> src_out_arr
80
--                                |          | dp   |
81
--                             (0)|          | block|
82
--                                | snk_in   | gen  |
83
--                                \--------->| arr  |
84
--                                           |------|
85
--
86
-- * Example 2: Use snk_in.valid to recreate sop, eop, bsn and check that the
87
--              local sync is aligned with the snk_in.sync. If the snk_in.sync
88
--              does not coincide with the local sync, then stop the output of
89
--              blocks until the snk_in.sync occurs again.
90
--              
91
--   - g_check_input_sync = True
92
--   - g_nof_pages_bsn    = 0
93
--   
94
--                                           |------|
95
--               snk_in_arr() ----*--------->|      |----> src_out_arr
96
--                                |          | dp   |
97
--                             (0)|          | block|
98
--                                | snk_in   | gen  |
99
--                                \--------->| arr  |
100
--                                           |------|
101
--
102
-- * Example 3: Use snk_in.valid to recreate sop, eop, bsn for a DP
103
--              function that only passes on the valid. However use snk_in.sync
104
--              to delay the snk_in.bsn by g_nof_pages_bsn to account for the
105
--              block latency of the upstream DP components that did not pass
106
--              on the snk_in.bsn.
107
--
108
--   - g_check_input_sync = False
109
--   - g_nof_pages_bsn    >= 1
110
--
111
--                  |-----|    snk_in_arr()  |------|
112
--         -----*-->|     |-------*--------->|      |----> src_out_arr
113
--              |   | DP  |       |          | dp   |
114
--              |   |     |    (0)|          | block|
115
--              |   |     |       | snk_in   | gen  |
116
--              |   |     |       \--*------>| arr  |
117
--          sync|   |-----|          ^       |------|
118
--          bsn |                    |
119
--              \--------------------/
120
--
121
-- Remarks:
122
-- . This dp_block_gen_valid_arr relates to:
123
--   - dp_bsn_source.vhd
124
--   - dp_block_gen.vhd when snk_in.valid is used for flow control (so when
125
--     g_use_src_in=FALSE). This is why thsi dp_block_gen_valid_arr is called
126
--     with '_valid' in its name.
127
--   - dp_counter.vhd
128
--   - dp_paged_sop_eop_reg.vhd
129
--   - dp_fifo_info.vhd
130
--   - dp_sync_checker.vhd
131
-- . This dp_block_gen_valid_arr has no siso flow control, although enable
132
--   could be used as siso.xon.
133
-- . The channel, empty and err fields are passed on to the output. Typically
134
--   these fields are not used with DSP data. However this scheme still
135
--   allows setting these fields to a fixed value via snk_in.
136
-- . Using g_check_input_sync=True is similar to using a dp_sync_checker in
137
--   front of this dp_block_gen_valid_arr. However the advantage of
138
--   dp_sync_checker is that it provides monitoring and control via MM.
139
 
140
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib, common_components_lib;
141
USE IEEE.STD_LOGIC_1164.ALL;
142
USE IEEE.NUMERIC_STD.ALL;
143
USE common_pkg_lib.common_pkg.ALL;
144
USE dp_pkg_lib.dp_stream_pkg.ALL;
145
 
146
ENTITY dp_block_gen_valid_arr IS
147
  GENERIC (
148
    g_nof_streams           : POSITIVE := 1;
149
    g_nof_data_per_block    : POSITIVE := 1;
150
    g_nof_blk_per_sync      : POSITIVE := 8;
151
    g_check_input_sync      : BOOLEAN := FALSE;
152
    g_nof_pages_bsn         : NATURAL := 0;
153
    g_restore_global_bsn    : BOOLEAN := FALSE
154
  );
155
  PORT (
156
    rst         : IN  STD_LOGIC;
157
    clk         : IN  STD_LOGIC;
158
    -- Streaming sink
159
    snk_in      : IN  t_dp_sosi;  -- = snk_in_arr(0)
160
    snk_in_arr  : IN  t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
161
    -- Streaming source
162
    src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
163
    -- Control
164
    enable      : IN  STD_LOGIC := '1'  -- can connect via MM or could also connect to a src_in.xon
165
  );
166
END dp_block_gen_valid_arr;
167
 
168
 
169
ARCHITECTURE rtl OF dp_block_gen_valid_arr IS
170
 
171
  -- Check consistancy of the parameters, the function return value is void, because always true or abort due to failure
172
  FUNCTION parameter_asserts(g_check_input_sync : BOOLEAN; g_nof_pages_bsn : NATURAL) return BOOLEAN IS
173
  BEGIN
174
    IF g_check_input_sync=TRUE THEN
175
      ASSERT g_nof_pages_bsn=0 REPORT "When g_check_input_sync=TRUE then g_nof_pages_bsn must be 0." SEVERITY FAILURE;
176
      -- because snk_in.sync and snk_in.bsn are then already aligned with the first snk_in.valid
177
    END IF;
178
    IF g_nof_pages_bsn>0 THEN
179
      ASSERT g_check_input_sync=FALSE REPORT "When g_nof_pages_bsn>0 then g_check_input_sync must be FALSE." SEVERITY FAILURE;
180
      -- because snk_in.sync and snk_in.bsn are then NOT aligned with the first snk_in.valid
181
    END IF;
182
    RETURN TRUE;
183
  END parameter_asserts;
184
 
185
  CONSTANT c_parameters_ok : BOOLEAN := parameter_asserts(g_check_input_sync, g_nof_pages_bsn);
186
 
187
  TYPE t_state IS (s_sop, s_data, s_eop);
188
 
189
  TYPE t_reg IS RECORD  -- local registers
190
    state       : t_state;
191
    data_cnt    : NATURAL RANGE 0 TO g_nof_data_per_block;
192
    blk_cnt     : NATURAL RANGE 0 TO g_nof_blk_per_sync;
193
    reg_sosi    : t_dp_sosi;
194
  END RECORD;
195
 
196
  CONSTANT c_reg_rst  : t_reg := (s_sop, 0, 0, c_dp_sosi_rst);
197
 
198
  SIGNAL in_sosi         : t_dp_sosi;
199
  SIGNAL in_sync_wr_en   : STD_LOGIC_VECTOR(g_nof_pages_bsn-1 DOWNTO 0);
200
  SIGNAL in_bsn_buffer   : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
201
 
202
  SIGNAL out_sosi        : t_dp_sosi;
203
  SIGNAL nxt_src_out_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
204
 
205
  -- Define the local registers in t_reg record
206
  SIGNAL r         : t_reg;
207
  SIGNAL nxt_r     : t_reg;
208
 
209
BEGIN
210
 
211
  p_clk : PROCESS(rst, clk)
212
  BEGIN
213
    IF rst='1' THEN
214
      r           <= c_reg_rst;
215
      src_out_arr <= (OTHERS=>c_dp_sosi_rst);
216
    ELSIF rising_edge(clk) THEN
217
      r           <= nxt_r;
218
      src_out_arr <= nxt_src_out_arr;
219
    END IF;
220
  END PROCESS;
221
 
222
  no_bsn_buffer : IF g_nof_pages_bsn=0 GENERATE
223
    in_sosi <= snk_in;
224
  END GENERATE;
225
 
226
  gen_bsn_buffer : IF g_nof_pages_bsn>0 GENERATE
227
    -- Buffer input BSN at each input sync
228
    in_sync_wr_en <= (OTHERS=>snk_in.sync);
229
 
230
    u_paged_bsn : ENTITY common_components_lib.common_paged_reg
231
    GENERIC MAP (
232
      g_data_w    => c_dp_stream_bsn_w,
233
      g_nof_pages => g_nof_pages_bsn
234
    )
235
    PORT MAP (
236
      rst          => rst,
237
      clk          => clk,
238
      wr_en        => in_sync_wr_en,
239
      wr_dat       => snk_in.bsn,
240
      out_dat      => in_bsn_buffer
241
    );
242
 
243
    p_snk_in : PROCESS(snk_in, in_bsn_buffer)
244
    BEGIN
245
      in_sosi      <= snk_in;
246
      in_sosi.sync <= '0';
247
      in_sosi.bsn  <= in_bsn_buffer;
248
    END PROCESS;
249
  END GENERATE;
250
 
251
  -- Determine the output info and output ctrl using snk_in and r.reg_sosi
252
  p_state : PROCESS(r, enable, in_sosi, snk_in)
253
  BEGIN
254
    nxt_r <= r;
255
 
256
    -- default output in_sosi, hold output bsn and set the output ctrl to '0'
257
    nxt_r.reg_sosi       <= in_sosi;
258
    nxt_r.reg_sosi.bsn   <= r.reg_sosi.bsn;
259
    nxt_r.reg_sosi.valid <= '0';
260
    nxt_r.reg_sosi.sop   <= '0';
261
    nxt_r.reg_sosi.eop   <= '0';
262
    nxt_r.reg_sosi.sync  <= '0';
263
 
264
    CASE r.state IS
265
      WHEN s_sop =>
266
        nxt_r.data_cnt <= 0;    -- For clarity init data count to 0 (because it will become 1 anyway at sop)
267
        IF enable='0' THEN      -- Check enable in state s_sop to ensure that disable cannot happen during a block
268
          nxt_r.blk_cnt <= 0;   -- If disabled then reset block generator and remain in this state
269
        ELSE                    -- Enabled block generator
270
          IF snk_in.valid='1' THEN    -- Once enabled the complete block will be output dependent on the input valid
271
            -- maintain blk_cnt for output sync interval, the blk_cnt is the local bsn that wraps at every sync
272
            IF r.blk_cnt>=g_nof_blk_per_sync-1 THEN
273
              nxt_r.blk_cnt <= 0;
274
            ELSE
275
              nxt_r.blk_cnt <= r.blk_cnt+1;
276
            END IF;
277
 
278
            -- create local sync and pass on input bsn at local sync
279
            IF r.blk_cnt=0 THEN                        -- output sync starts at first input valid
280
              nxt_r.reg_sosi.sync <= '1';               -- output sync for this block
281
              nxt_r.reg_sosi.bsn  <= in_sosi.bsn;       -- output input bsn at sync
282
            ELSE
283
              nxt_r.reg_sosi.bsn  <= TO_DP_BSN(r.blk_cnt);  -- output local bsn for the subsequent blocks
284
            END IF;
285
 
286
            nxt_r.reg_sosi.valid <= '1';
287
            nxt_r.reg_sosi.sop   <= '1';
288
 
289
            IF g_nof_data_per_block=1 THEN
290
              nxt_r.reg_sosi.eop <= '1';  -- single word block
291
            ELSE
292
              nxt_r.data_cnt <= 1;       -- start of multi word block
293
              nxt_r.state <= s_data;
294
            END IF;
295
 
296
            -- if enabled then check input sync and stop the new block output if the local sync does not coincide with the input sync
297
            IF g_check_input_sync=TRUE THEN
298
              IF r.blk_cnt=0 THEN
299
                IF snk_in.sync='0' THEN
300
                  nxt_r.reg_sosi.valid <= '0';  -- undo all ctrl preparations for the new block
301
                  nxt_r.reg_sosi.sop   <= '0';
302
                  nxt_r.reg_sosi.eop   <= '0';
303
                  nxt_r.reg_sosi.sync  <= '0';
304
                  nxt_r.blk_cnt <= 0;          -- restart blk_cnt
305
                  nxt_r.state <= s_sop;        -- remain in this state and wait for snk_in.sync
306
                END IF;
307
              END IF;
308
            END IF;
309
          END IF;
310
        END IF;
311
      WHEN s_data =>
312
        IF snk_in.valid='1' THEN
313
          nxt_r.data_cnt <= r.data_cnt+1;
314
          nxt_r.reg_sosi.valid <= '1';
315
          IF r.data_cnt=g_nof_data_per_block-2 THEN
316
            nxt_r.state <= s_eop;
317
          END IF;
318
        END IF;
319
      WHEN OTHERS =>  -- s_eop
320
        IF snk_in.valid='1' THEN
321
          nxt_r.reg_sosi.valid <= '1';
322
          nxt_r.reg_sosi.eop   <= '1';
323
          nxt_r.state <= s_sop;
324
        END IF;
325
    END CASE;
326
  END PROCESS;
327
 
328
  -- Use local BSN that counts from 0 during sync interval, or restore global BSN between syncs
329
  use_local_bsn : IF g_restore_global_bsn=FALSE GENERATE
330
    out_sosi <= nxt_r.reg_sosi;
331
  END GENERATE;
332
 
333
  use_global_bsn : IF g_restore_global_bsn=TRUE GENERATE
334
    u_dp_bsn_restore_global : ENTITY work.dp_bsn_restore_global
335
    GENERIC MAP (
336
      g_bsn_w    => c_dp_stream_bsn_w,
337
      g_pipeline => 0       -- pipeline registering is done via nxt_src_out_arr
338
    )
339
    PORT MAP (
340
      rst          => rst,
341
      clk          => clk,
342
      -- ST sink
343
      snk_in       => nxt_r.reg_sosi,
344
      -- ST source
345
      src_out      => out_sosi
346
    );
347
  END GENERATE;
348
 
349
  -- Combine input data with the same out_put info and output ctrl for all streams
350
  nxt_src_out_arr <= func_dp_stream_arr_combine_data_info_ctrl(snk_in_arr, out_sosi, out_sosi);
351
 
352
END rtl;

powered by: WebSVN 2.1.0

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