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

Subversion Repositories astron_diagnostics

[/] [astron_diagnostics/] [trunk/] [diag_data_buffer.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 : Capture a block of streaming data for analysis via MM access
23
-- Description :
24
--   The first g_nof_data valid streaming data input words are stored in the
25
--   data buffer. Then they can be read via the MM interface. Dependent on
26
--   g_use_in_sync the nxt block of valid streaming data input words gets
27
--   stored when a new in_sync occurs or when the last word was read from via
28
--   the MM interface.
29
-- Remarks:
30
-- . The actual RAM usage depends on g_data_w. Unused bits are forced to '0'
31
--   when read.
32
-- . The c_mm_factor must be a power of 2 factor. Typically c_mm_factor=1 is
33
--   sufficient for most purposes. If the application only requires
34
--   eg. c_mm_factor=3 then it needs to extend the data to c_mm_factor=4.
35
-- . If c_mm_factor=2 then in_data[g_data_w/2-1:0] will appear at MM address
36
--   even and in_data[g_data_w-1:g_data_w/2] at address odd.
37
--   The advantage of splitting at g_data_w/2 instead of at c_word_w=32 is
38
--   that streaming 36b data can then map on 18b RAM still fit in a single
39
--   RAM block. Whereas mapping the LS 32b part at even address and the MS 4b
40
--   part at odd address would require using c_word_w=32b RAM that could
41
--   require two RAM blocks. For g_data_w=2*c_word_w=64b there is no
42
--   difference between these 2 schemes. Hence by rising the g_data_w to a
43
--   power of 2 multiple of 32b the user can enforce using splitting the data
44
--   a c_word_w parts.
45
 
46
LIBRARY IEEE, common_pkg_lib, mm_lib, technology_lib, common_ram_lib, common_counter_lib, common_components_lib;
47
USE IEEE.std_logic_1164.ALL;
48
USE IEEE.numeric_std.ALL;
49
USE common_pkg_lib.common_pkg.ALL;
50
USE common_ram_lib.common_ram_pkg.ALL;
51
USE work.diag_pkg.ALL;
52
USE technology_lib.technology_select_pkg.ALL;
53
 
54
ENTITY diag_data_buffer IS
55
  GENERIC (
56
    g_technology  : NATURAL := c_tech_select_default;
57
    g_data_w      : NATURAL := 32;
58
    g_nof_data    : NATURAL := 1024;
59
    g_use_in_sync : BOOLEAN := FALSE   -- when TRUE start filling the buffer at the in_sync, else after the last word was read
60
  );
61
  PORT (
62
    -- Memory-mapped clock domain
63
    mm_rst       : IN  STD_LOGIC;
64
    mm_clk       : IN  STD_LOGIC;
65
 
66
    ram_mm_mosi  : IN  t_mem_mosi;  -- read and overwrite access to the data buffer
67
    ram_mm_miso  : OUT t_mem_miso;
68
 
69
    reg_mm_mosi  : IN  t_mem_mosi := c_mem_mosi_rst;
70
    reg_mm_miso  : OUT t_mem_miso;
71
 
72
    -- Streaming clock domain
73
    st_rst       : IN  STD_LOGIC;
74
    st_clk       : IN  STD_LOGIC;
75
 
76
    in_data      : IN  STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
77
    in_sync      : IN  STD_LOGIC := '0';
78
    in_val       : IN  STD_LOGIC
79
  );
80
END diag_data_buffer;
81
 
82
 
83
ARCHITECTURE rtl OF diag_data_buffer IS
84
 
85
  CONSTANT c_mm_factor     : NATURAL := ceil_div(g_data_w, c_word_w);  -- must be a power of 2 multiple
86
 
87
  CONSTANT c_nof_data_mm   : NATURAL := g_nof_data*c_mm_factor;
88
  CONSTANT g_data_mm_w     : NATURAL := g_data_w/c_mm_factor;
89
 
90
  CONSTANT c_buf_mm        : t_c_mem := (latency  => 1,
91
                                         adr_w    => ceil_log2(c_nof_data_mm),
92
                                         dat_w    => g_data_mm_w,
93
                                         nof_dat  => c_nof_data_mm,
94
                                         init_sl  => '0');
95
 
96
  CONSTANT c_buf_st        : t_c_mem := (latency  => 1,
97
                                         adr_w    => ceil_log2(g_nof_data),
98
                                         dat_w    => g_data_w,
99
                                         nof_dat  => g_nof_data,
100
                                         init_sl  => '0');
101
 
102
  CONSTANT c_reg           : t_c_mem := (latency  => 1,
103
                                         adr_w    => c_diag_db_reg_adr_w,
104
                                         dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
105
                                         nof_dat  => c_diag_db_reg_nof_dat,   -- 1: word_cnt; 0:sync_cnt
106
                                         init_sl  => '0');
107
 
108
  SIGNAL i_ram_mm_miso   : t_mem_miso := c_mem_miso_rst;   -- used to avoid vsim-8684 error "No drivers exist" for the unused fields
109
 
110
  SIGNAL rd_last         : STD_LOGIC;
111
  SIGNAL wr_sync         : STD_LOGIC;
112
 
113
  SIGNAL wr_done         : STD_LOGIC;
114
  SIGNAL nxt_wr_done     : STD_LOGIC;
115
 
116
  SIGNAL wr_data         : STD_LOGIC_VECTOR(c_buf_st.dat_w-1 DOWNTO 0);
117
  SIGNAL nxt_wr_data     : STD_LOGIC_VECTOR(c_buf_st.dat_w-1 DOWNTO 0);
118
  SIGNAL wr_addr         : STD_LOGIC_VECTOR(c_buf_st.adr_w-1 DOWNTO 0);
119
  SIGNAL nxt_wr_addr     : STD_LOGIC_VECTOR(c_buf_st.adr_w-1 DOWNTO 0);
120
  SIGNAL wr_en           : STD_LOGIC;
121
  SIGNAL nxt_wr_en       : STD_LOGIC;
122
 
123
  SIGNAL reg_rd_arr      : STD_LOGIC_VECTOR(c_reg.nof_dat-1 DOWNTO 0);
124
  SIGNAL reg_slv         : STD_LOGIC_VECTOR(c_reg.nof_dat*c_word_w-1 DOWNTO 0);
125
 
126
  SIGNAL sync_cnt_clr    : STD_LOGIC := '0';
127
  SIGNAL sync_cnt        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- Nof times buffer has been written
128
  SIGNAL word_cnt        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS=>'0');
129
 
130
BEGIN
131
 
132
  ASSERT c_mm_factor=2**true_log2(c_mm_factor) REPORT "Only support mixed width data that uses a power of 2 multiple." SEVERITY FAILURE;
133
 
134
  ram_mm_miso <= i_ram_mm_miso;
135
 
136
  rd_last <= '1' WHEN UNSIGNED(ram_mm_mosi.address(c_buf_mm.adr_w-1 DOWNTO 0))=c_nof_data_mm-1 AND ram_mm_mosi.rd='1' ELSE '0';
137
 
138
  -- Determine the write trigger
139
  use_rd_last : IF g_use_in_sync=FALSE GENERATE
140
    u_wr_sync : ENTITY common_components_lib.common_spulse
141
    GENERIC MAP (
142
      g_delay_len => c_meta_delay_len
143
    )
144
    PORT MAP (
145
      in_rst    => mm_rst,
146
      in_clk    => mm_clk,
147
      in_pulse  => rd_last,
148
      out_rst   => st_rst,
149
      out_clk   => st_clk,
150
      out_pulse => wr_sync
151
    );
152
  END GENERATE;
153
 
154
  use_in_sync : IF g_use_in_sync=TRUE GENERATE
155
    sync_cnt_clr <= rd_last;  -- clear sync_cnt register on read of last data
156
    wr_sync      <= in_sync;
157
  END GENERATE;
158
 
159
  p_st_clk : PROCESS (st_clk, st_rst)
160
  BEGIN
161
    IF st_rst='1' THEN
162
      wr_data <= (OTHERS => '0');
163
      wr_addr <= (OTHERS => '0');
164
      wr_en   <= '0';
165
      wr_done <= '0';
166
    ELSIF rising_edge(st_clk) THEN
167
      wr_data <= nxt_wr_data;
168
      wr_addr <= nxt_wr_addr;
169
      wr_en   <= nxt_wr_en;
170
      wr_done <= nxt_wr_done;
171
    END IF;
172
  END PROCESS;
173
 
174
  -- Write access control
175
  nxt_wr_data <= in_data;
176
  nxt_wr_en   <= in_val AND NOT nxt_wr_done;
177
 
178
  p_wr_addr : PROCESS (wr_done, wr_addr, wr_sync, wr_en)
179
  BEGIN
180
    nxt_wr_done <= wr_done;
181
    nxt_wr_addr <= wr_addr;
182
    IF wr_sync='1' THEN
183
      nxt_wr_done <= '0';
184
      nxt_wr_addr <= (OTHERS => '0');
185
    ELSIF wr_en='1' THEN
186
      IF UNSIGNED(wr_addr)=g_nof_data-1 THEN
187
        nxt_wr_done <= '1';   -- keep wr_addr, do not allow wr_addr increment >= g_nof_data to avoid RAM address out-of-bound warning in Modelsim in case c_buf.nof_dat < 2**c_buf.adr_w
188
      ELSE
189
        nxt_wr_addr <= INCR_UVEC(wr_addr, 1);
190
      END IF;
191
    END IF;
192
  END PROCESS;
193
 
194
  u_buf : ENTITY common_ram_lib.common_ram_crw_crw_ratio
195
  GENERIC MAP (
196
    g_technology => g_technology,
197
    g_ram_a     => c_buf_mm,
198
    g_ram_b     => c_buf_st,
199
    g_init_file => "UNUSED"
200
  )
201
  PORT MAP (
202
    -- MM read/write port clock domain
203
    rst_a    => mm_rst,
204
    clk_a    => mm_clk,
205
    wr_en_a  => ram_mm_mosi.wr,
206
    wr_dat_a => ram_mm_mosi.wrdata(c_buf_mm.dat_w-1 DOWNTO 0),
207
    adr_a    => ram_mm_mosi.address(c_buf_mm.adr_w-1 DOWNTO 0),
208
    rd_en_a  => ram_mm_mosi.rd,
209
    rd_dat_a => i_ram_mm_miso.rddata(c_buf_mm.dat_w-1 DOWNTO 0),
210
    rd_val_a => i_ram_mm_miso.rdval,
211
 
212
    -- ST write only port clock domain
213
    rst_b     => st_rst,
214
    clk_b     => st_clk,
215
    wr_en_b   => wr_en,
216
    wr_dat_b  => wr_data,
217
    adr_b     => wr_addr,
218
    rd_en_b   => '0',
219
    rd_dat_b  => OPEN,
220
    rd_val_b  => OPEN
221
  );
222
 
223
  u_reg : ENTITY mm_lib.common_reg_r_w_dc
224
  GENERIC MAP (
225
    g_reg       => c_reg
226
  )
227
  PORT MAP (
228
    -- Clocks and reset
229
    mm_rst      => mm_rst,
230
    mm_clk      => mm_clk,
231
    st_rst      => st_rst,
232
    st_clk      => st_clk,
233
 
234
    -- Memory Mapped Slave in mm_clk domain
235
    sla_in      => reg_mm_mosi,
236
    sla_out     => reg_mm_miso,
237
 
238
    -- MM registers in st_clk domain
239
    reg_wr_arr  => OPEN,
240
    reg_rd_arr  => reg_rd_arr,
241
    in_reg      => reg_slv,
242
    out_reg     => OPEN
243
  );
244
 
245
  reg_slv <= word_cnt & sync_cnt;
246
 
247
  u_word_cnt : ENTITY common_counter_lib.common_counter
248
  PORT MAP (
249
    rst     => st_rst,
250
    clk     => st_clk,
251
    cnt_en  => wr_en,
252
    cnt_clr => wr_sync,
253
    count   => word_cnt
254
  );
255
 
256
  u_sync_cnt : ENTITY common_counter_lib.common_counter
257
  PORT MAP (
258
    rst     => st_rst,
259
    clk     => st_clk,
260
    cnt_en  => wr_sync,
261
    cnt_clr => sync_cnt_clr,
262
    count   => sync_cnt
263
  );
264
 
265
END rtl;
266
 

powered by: WebSVN 2.1.0

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