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

Subversion Repositories astron_diagnostics

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3 3 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 3 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: Block generator repeating a data pattern
22
-- Description:
23
--   The data pattern is read via the buf_* MM interface. The output data
24
--   block is controlled via ctrl of type t_diag_block_gen with fields:
25
--
26
--     enable             : sl  -- block enable immediately
27
--     enable_sync        : sl  -- block enable at next en_sync pulse
28
--     samples_per_packet : slv -- number of valid per block, from sop to eop
29
--     blocks_per_sync    : slv -- number of blocks per sync interval
30
--     gapsize            : slv -- number of clk cycles between blocks, so
31
--                                 between last eop and next sop
32
--     mem_low_adrs       : slv -- block start address at MM interface
33
--     mem_high_adrs      : slv -- end address at MM interface
34
--     bsn_init           : slv -- BSN of first output block
35
--                                          
36
--   The MM reading starts at mem_low_adrs when the BG is first enabled. If
37
--   the mem_high_adrs-mem_low_adrs+1 < samples_per_packet then the reading
38
--   wraps and continues from mem_low_adrs. For every new block the reading
39
--   continues where it left in the previous block. This MM reading scheme
40
--   allows using a periodic data pattern that can extends accross blocks and
41
--   sync intervals, because is continues for as long as the BG remains
42
--   enabled.
43
--
44
--   The input en_sync can be used as trigger to start multiple BG at the same
45
--   clk cycle. The BG creates a out_sosi.sync at the first sop and the sop of
46
--   every blocks_per_sync.
47
--
48
--   The current block is finished properly after enable gows low, to ensure 
49
--   that all blocks have the same length. A new ctrl is accepted after a
50
--   current block has finished, to ensure that no fractional blocks will 
51
--   enter the stream.
52
--
53
--   The BG supports block flow control via out_siso.xon. The BG also supports
54
--   sample flow control via out_siso.ready.
55
--
56
--   The read data is resized and output as unsigned via:
57
--   . out_sosi.data(g_buf_dat_w-1:0).
58
--   The read data is also output as complex data via:
59
--   . out_sosi.im(g_buf_dat_w  -1:g_buf_dat_w/2)
60
--   . out_sosi.re(g_buf_dat_w/2-1:            0)
61
 
62
library IEEE, common_pkg_lib, dp_pkg_lib;
63
use IEEE.STD_LOGIC_1164.ALL;
64
use IEEE.NUMERIC_STD.ALL;
65
use common_pkg_lib.common_pkg.ALL;
66
use work.diag_pkg.ALL;
67
use dp_pkg_lib.dp_stream_pkg.ALL;
68
 
69
entity diag_block_gen is
70
  generic (
71
    g_blk_sync   : boolean := false;  -- when true use active sync during entire block, else use single clock cycle sync pulse
72
    g_buf_dat_w  : natural := 32;
73
    g_buf_addr_w : natural := 7
74
  );
75
  port (
76
    rst          : in  std_logic;
77
    clk          : in  std_logic;
78
    buf_addr     : out std_logic_vector(g_buf_addr_w-1 downto 0);
79
    buf_rden     : out std_logic;
80
    buf_rddat    : in  std_logic_vector(g_buf_dat_w-1 downto 0);
81
    buf_rdval    : in  std_logic;
82
    ctrl         : in  t_diag_block_gen;
83
    en_sync      : in  std_logic := '1';
84
    out_siso     : in  t_dp_siso := c_dp_siso_rdy;
85
    out_sosi     : out t_dp_sosi
86
  );
87
 
88
end diag_block_gen;
89
 
90
architecture rtl of diag_block_gen is
91
 
92
  type state_type is (s_idle, s_block, s_gap);
93
 
94
  type reg_type is record
95
    ctrl_reg    : t_diag_block_gen;  -- capture ctrl
96
    blk_en      : std_logic;  -- enable at block level
97
    blk_xon     : std_logic;  -- siso.xon at block level, the BG continues but the sosi control depend on xon (the BG does not support siso.ready)
98
    blk_sync    : std_logic;  -- block sync alternative of the pulse sync
99
    pls_sync    : std_logic;  -- pulse sync
100
    valid       : std_logic;
101
    sop         : std_logic;
102
    eop         : std_logic;
103
    rd_ena      : std_logic;
104
    samples_cnt : natural range 0 to 2**c_diag_bg_samples_per_packet_w-1;
105
    blocks_cnt  : natural range 0 to 2**c_diag_bg_blocks_per_sync_w-1;
106
    bsn_cnt     : std_logic_vector(c_diag_bg_bsn_init_w-1 downto 0);  -- = c_dp_stream_bsn_w
107
    mem_cnt     : natural range 0 to 2**g_buf_addr_w-1;
108
    state       : state_type;   -- The state machine. 
109
  end record;
110
 
111
  signal r, rin     : reg_type;
112
  signal out_sosi_i : t_dp_sosi := c_dp_sosi_rst;  -- Signal used to assign reset values to output
113
 
114
begin
115
 
116
    p_comb : process(r, rst, ctrl, en_sync, out_siso)
117
      variable v                    : reg_type;
118
      variable v_samples_per_packet : natural;
119
      variable v_gapsize            : natural;
120
      variable v_blocks_per_sync    : natural;
121
      variable v_mem_low_adrs       : natural;
122
      variable v_mem_high_adrs      : natural;
123
    begin
124
 
125
      v_samples_per_packet := TO_UINT(r.ctrl_reg.samples_per_packet);
126
      v_gapsize            := TO_UINT(r.ctrl_reg.gapsize);
127
      v_blocks_per_sync    := TO_UINT(r.ctrl_reg.blocks_per_sync);
128
      v_mem_low_adrs       := TO_UINT(r.ctrl_reg.mem_low_adrs);
129
      v_mem_high_adrs      := TO_UINT(r.ctrl_reg.mem_high_adrs);
130
 
131
      v                   := r;     -- default hold all r fields
132
      v.pls_sync          := '0';
133
      v.valid             := '0';
134
      v.sop               := '0';
135
      v.eop               := '0';
136
      v.rd_ena            := '0';
137
 
138
      -- Control block generator enable
139
      if ctrl.enable='0' then
140
        v.blk_en := '0';  -- disable immediately
141
      elsif ctrl.enable_sync='0' then
142
        v.blk_en := '1';  -- enable immediately or keep enabled
143
      elsif en_sync='1' then
144
        v.blk_en := '1';  -- enable at input sync pulse or keep enabled
145
      end if;
146
 
147
      -- The pulse sync is high at the sop of the first block, the block sync is high during the entire block until the eop
148
      if r.eop='1' then
149
        v.blk_sync := '0';
150
      end if;
151
 
152
      -- Increment the block sequence number counter after each block
153
      if r.eop='1' then
154
        v.bsn_cnt := incr_uvec(r.bsn_cnt, 1);
155
      end if;
156
 
157
      case r.state is
158
        when s_idle =>
159
          v.ctrl_reg    := ctrl;        -- accept new control settings
160
          v.blk_xon     := out_siso.xon;
161
          v.blk_sync    := '0';
162
          v.samples_cnt := 0;
163
          v.blocks_cnt  := 0;
164
          v.bsn_cnt     := ctrl.bsn_init;
165
          v.mem_cnt     := v_mem_low_adrs;
166
          if r.blk_en = '1' then       -- Wait until enabled
167
            if out_siso.xon='1' then   -- Wait until XON is 1
168
              v.rd_ena      := '1';
169
              v.state       := s_block;
170
            end if;
171
          end if;
172
 
173
        when s_block =>
174
          if out_siso.ready='1' then
175
 
176
            v.rd_ena := '1';  -- read next data
177
            if r.samples_cnt = 0 and r.blocks_cnt = 0 then
178
              v.pls_sync    := '1';                      -- Always start with a pulse sync          
179
              v.blk_sync    := '1';
180
              v.sop         := '1';
181
              v.samples_cnt := v.samples_cnt + 1;
182
            elsif r.samples_cnt = 0 then
183
              v.sop         := '1';
184
              v.samples_cnt := v.samples_cnt + 1;
185
            elsif r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0 and r.blocks_cnt >= v_blocks_per_sync-1 then
186
              v.eop         := '1';
187
              v.ctrl_reg    := ctrl;      -- accept new control settings at end of block when gapsize=0
188
              v.samples_cnt := 0;
189
              v.blocks_cnt  := 0;
190
            elsif r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0 then
191
              v.eop         := '1';
192
              v.ctrl_reg    := ctrl;      -- accept new control settings at end of block when gapsize=0
193
              v.samples_cnt := 0;
194
              v.blocks_cnt  := r.blocks_cnt + 1;
195
            elsif r.samples_cnt >= v_samples_per_packet-1 then
196
              v.eop         := '1';
197
              v.samples_cnt := 0;
198
              v.rd_ena      := '0';
199
              v.state       := s_gap;
200
            else
201
              v.samples_cnt := r.samples_cnt + 1;
202
            end if;
203
            v.valid  := '1';  -- output pending data
204
 
205
            if r.mem_cnt >= v_mem_high_adrs then
206
              v.mem_cnt := v_mem_low_adrs;
207
            else
208
              v.mem_cnt := r.mem_cnt + 1;
209
            end if;
210
 
211
            if v.eop = '1' and r.blk_en = '0' then
212
              v.state := s_idle;          -- accept disable after eop, not during block
213
            end if;
214
            if r.eop = '1' then
215
              v.blk_xon := out_siso.xon;  -- accept XOFF after eop, not during block
216
            end if;
217
 
218
          end if;  -- out_siso.ready='1'
219
 
220
        when s_gap =>
221
          if r.samples_cnt >= v_gapsize-1 and r.blocks_cnt >= v_blocks_per_sync-1 then
222
            v.ctrl_reg    := ctrl;      -- accept new control settings at end of gap
223
            v.samples_cnt := 0;
224
            v.blocks_cnt  := 0;
225
            v.rd_ena      := '1';
226
            v.state       := s_block;
227
          elsif r.samples_cnt >= v_gapsize-1 then
228
            v.ctrl_reg    := ctrl;      -- accept new control settings at end of gap
229
            v.samples_cnt := 0;
230
            v.blocks_cnt  := r.blocks_cnt + 1;
231
            v.rd_ena      := '1';
232
            v.state       := s_block;
233
          else
234
            v.samples_cnt := r.samples_cnt + 1;
235
          end if;
236
 
237
          if r.blk_en = '0' then
238
            v.state := s_idle;
239
          end if;
240
          v.blk_xon := out_siso.xon;
241
 
242
        when others =>
243
          v.state := s_idle;
244
 
245
      end case;
246
 
247
      if rst = '1' then
248
        v.ctrl_reg    := c_diag_block_gen_rst;
249
        v.blk_en      := '0';
250
        v.blk_xon     := '0';
251
        v.blk_sync    := '0';
252
        v.pls_sync    := '0';
253
        v.valid       := '0';
254
        v.sop         := '0';
255
        v.eop         := '0';
256
        v.rd_ena      := '0';
257
        v.samples_cnt := 0;
258
        v.blocks_cnt  := 0;
259
        v.bsn_cnt     := (others=>'0');
260
        v.mem_cnt     := 0;
261
        v.state       := s_idle;
262
      end if;
263
 
264
      rin <= v;
265
 
266
    end process;
267
 
268
    p_regs : process(rst, clk)
269
    begin
270
      if rising_edge(clk) then
271
        r <= rin;
272
      end if;
273
    end process;
274
 
275
    -- Connect to the outside world
276
    out_sosi_i.sop   <= r.sop      and r.blk_xon;
277
    out_sosi_i.eop   <= r.eop      and r.blk_xon;
278
    out_sosi_i.sync  <= r.pls_sync and r.blk_xon when g_blk_sync=false else r.blk_sync and r.blk_xon;
279
    out_sosi_i.valid <= r.valid    and r.blk_xon;
280
    out_sosi_i.bsn   <= r.bsn_cnt;
281
    out_sosi_i.re    <= RESIZE_DP_DSP_DATA(buf_rddat(g_buf_dat_w/2-1 downto 0));               -- treat as signed
282
    out_sosi_i.im    <= RESIZE_DP_DSP_DATA(buf_rddat(g_buf_dat_w-1   downto g_buf_dat_w/2));   -- treat as signed
283
    out_sosi_i.data  <= RESIZE_DP_DATA(    buf_rddat(g_buf_dat_w-1   downto 0));               -- treat as unsigned
284
 
285
    out_sosi <= out_sosi_i;
286
    buf_addr <= TO_UVEC(r.mem_cnt, g_buf_addr_w);
287
    buf_rden <= r.rd_ena;
288
 
289
end rtl;

powered by: WebSVN 2.1.0

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