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 4

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

powered by: WebSVN 2.1.0

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