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 2

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

powered by: WebSVN 2.1.0

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