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

Subversion Repositories astron_ram

[/] [astron_ram/] [trunk/] [common_paged_ram_crw_crw.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: Multi page memory
22
-- Description:
23
--   When next_page_* pulses then the next access will occur in the next page.
24
-- Remarks:
25
-- . There are three architecture variants (default use "use_adr"):
26
--   . use_mux : Use multiplexer logic and one RAM per page
27
--   . use_adr : Use MSbit address lines and one buf RAM for all pages
28
--   . use_ofs : Use address offset adders and one buf RAM for all pages
29
-- . The "use_mux" variant requires the multiplexer logic but can be more
30
--   efficient regarding RAM usage than the "use_adr" variant.
31
--   The "use_ofs" variant requires address adder logic, but is optimal
32
--   regarding RAM usage in case the page size is not a power of 2, because the
33
--   pages are then mapped at subsequent addresses in the buf RAM.
34
-- . The "use_adr" variant is optimal for speed, so that is set as default.
35
 
36 4 danv
LIBRARY IEEE; --, technology_lib;
37 2 danv
USE IEEE.std_logic_1164.ALL;
38
USE IEEE.numeric_std.ALL;
39
LIBRARY common_pkg_lib;
40
USE common_pkg_lib.common_pkg.ALL;
41
USE work.common_ram_pkg.ALL;
42 4 danv
-- USE technology_lib.technology_select_pkg.ALL;
43 2 danv
 
44
ENTITY common_paged_ram_crw_crw IS
45
  GENERIC (
46 4 danv
    g_technology     : NATURAL := 0;
47 2 danv
    g_str            : STRING := "use_adr";
48
    g_data_w         : NATURAL;
49
    g_nof_pages      : NATURAL := 2;  -- >= 2
50
    g_page_sz        : NATURAL;
51
    g_start_page_a   : NATURAL := 0;
52
    g_start_page_b   : NATURAL := 0;
53
    g_rd_latency     : NATURAL := 1;
54
    g_true_dual_port : BOOLEAN := TRUE
55
  );
56
  PORT (
57
    rst_a       : IN  STD_LOGIC;
58
    rst_b       : IN  STD_LOGIC;
59
    clk_a       : IN  STD_LOGIC;
60
    clk_b       : IN  STD_LOGIC;
61
    clken_a     : IN  STD_LOGIC := '1';
62
    clken_b     : IN  STD_LOGIC := '1';
63
    next_page_a : IN  STD_LOGIC;
64
    adr_a       : IN  STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
65
    wr_en_a     : IN  STD_LOGIC := '0';
66
    wr_dat_a    : IN  STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
67
    rd_en_a     : IN  STD_LOGIC := '1';
68
    rd_dat_a    : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
69
    rd_val_a    : OUT STD_LOGIC;
70
    next_page_b : IN  STD_LOGIC;
71
    adr_b       : IN  STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
72
    wr_en_b     : IN  STD_LOGIC := '0';
73
    wr_dat_b    : IN  STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
74
    rd_en_b     : IN  STD_LOGIC := '1';
75
    rd_dat_b    : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
76
    rd_val_b    : OUT STD_LOGIC
77
  );
78
END common_paged_ram_crw_crw;
79
 
80
 
81
ARCHITECTURE rtl OF common_paged_ram_crw_crw IS
82
 
83
  TYPE t_page_sel_arr IS ARRAY (INTEGER RANGE <>) OF NATURAL RANGE 0 TO g_nof_pages-1;
84
 
85
  CONSTANT c_page_addr_w      : NATURAL := ceil_log2(g_page_sz);
86
 
87
  -- g_str = "use_mux" :
88
  CONSTANT c_page_ram         : t_c_mem := (latency  => g_rd_latency,
89
                                            adr_w    => c_page_addr_w,
90
                                            dat_w    => g_data_w,
91
                                            nof_dat  => g_page_sz,
92
                                            init_sl  => '0');
93
 
94
  TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
95
 
96
  -- g_str = "use_adr" :
97
  CONSTANT c_mem_nof_pages_w  : NATURAL := true_log2(g_nof_pages);
98
  CONSTANT c_mem_addr_w       : NATURAL := c_mem_nof_pages_w + c_page_addr_w;
99
  CONSTANT c_mem_nof_words    : NATURAL := g_nof_pages * 2**c_page_addr_w;  -- <= 2**c_mem_addr_w
100
 
101
  CONSTANT c_mem_ram          : t_c_mem := (latency  => g_rd_latency,
102
                                            adr_w    => c_mem_addr_w,
103
                                            dat_w    => g_data_w,
104
                                            nof_dat  => c_mem_nof_words,
105
                                            init_sl  => '0');
106
 
107
  -- g_str = "use_ofs" :
108
  CONSTANT c_buf_addr_w       : NATURAL := ceil_log2(g_nof_pages * g_page_sz);
109
  CONSTANT c_buf_nof_words    : NATURAL := g_nof_pages * g_page_sz;
110
 
111
  CONSTANT c_buf_ram          : t_c_mem := (latency  => g_rd_latency,
112
                                            adr_w    => c_buf_addr_w,
113
                                            dat_w    => g_data_w,
114
                                            nof_dat  => c_buf_nof_words,
115
                                            init_sl  => '0');
116
 
117
  -- >>> Page control
118
 
119
  -- g_str = "use_mux" and g_str = "use_adr" :
120
  -- . use page_sel direct for wr_en, rd_en, and address
121
  SIGNAL page_sel_a         : NATURAL RANGE 0 TO g_nof_pages-1;
122
  SIGNAL nxt_page_sel_a     : NATURAL;
123
  SIGNAL page_sel_b         : NATURAL RANGE 0 TO g_nof_pages-1;
124
  SIGNAL nxt_page_sel_b     : NATURAL;
125
 
126
  -- . use page_sel_dly to adjust for g_rd_latency of rd_dat and rd_val
127
  SIGNAL page_sel_a_dly     : t_page_sel_arr(0 TO g_rd_latency-1);
128
  SIGNAL nxt_page_sel_a_dly : t_page_sel_arr(0 TO g_rd_latency-1);
129
  SIGNAL page_sel_b_dly     : t_page_sel_arr(0 TO g_rd_latency-1);
130
  SIGNAL nxt_page_sel_b_dly : t_page_sel_arr(0 TO g_rd_latency-1);
131
 
132
  -- g_str = "use_ofs" :
133
  SIGNAL page_ofs_a         : NATURAL RANGE 0 TO c_buf_nof_words-1;
134
  SIGNAL nxt_page_ofs_a     : NATURAL;
135
  SIGNAL page_ofs_b         : NATURAL RANGE 0 TO c_buf_nof_words-1;
136
  SIGNAL nxt_page_ofs_b     : NATURAL;
137
 
138
  -- >>> Access control
139
 
140
  -- g_str = "use_mux" :
141
  SIGNAL page_wr_en_a       : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
142
  SIGNAL page_wr_dat_a      : t_data_arr(0 TO g_nof_pages-1);
143
  SIGNAL page_rd_en_a       : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
144
  SIGNAL page_rd_dat_a      : t_data_arr(0 TO g_nof_pages-1);
145
  SIGNAL page_rd_val_a      : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
146
 
147
  SIGNAL page_wr_en_b       : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
148
  SIGNAL page_wr_dat_b      : t_data_arr(0 TO g_nof_pages-1);
149
  SIGNAL page_rd_en_b       : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
150
  SIGNAL page_rd_dat_b      : t_data_arr(0 TO g_nof_pages-1);
151
  SIGNAL page_rd_val_b      : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
152
 
153
  -- g_str = "use_adr" :
154
  SIGNAL mem_adr_a          : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
155
  SIGNAL mem_adr_b          : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
156
 
157
  -- g_str = "use_ofs" :
158
  SIGNAL buf_adr_a          : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
159
  SIGNAL buf_adr_b          : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
160
 
161
BEGIN
162
 
163
  -- page select (for all) and page address offset (for use_ofs)
164
  p_reg_a : PROCESS (rst_a, clk_a)
165
  BEGIN
166
    IF rst_a = '1' THEN
167
      page_sel_a     <=          g_start_page_a;
168
      page_sel_a_dly <= (OTHERS=>g_start_page_a);
169
      page_ofs_a     <=          g_start_page_a * g_page_sz;
170
    ELSIF rising_edge(clk_a) THEN
171
      page_sel_a     <= nxt_page_sel_a;
172
      page_sel_a_dly <= nxt_page_sel_a_dly;
173
      page_ofs_a     <= nxt_page_ofs_a;
174
    END IF;
175
  END PROCESS;
176
 
177
  p_reg_b : PROCESS (rst_b, clk_b)
178
  BEGIN
179
    IF rst_b = '1' THEN
180
      page_sel_b     <=          g_start_page_b;
181
      page_sel_b_dly <= (OTHERS=>g_start_page_b);
182
      page_ofs_b     <=          g_start_page_b * g_page_sz;
183
    ELSIF rising_edge(clk_b) THEN
184
      page_sel_b     <= nxt_page_sel_b;
185
      page_sel_b_dly <= nxt_page_sel_b_dly;
186
      page_ofs_b     <= nxt_page_ofs_b;
187
    END IF;
188
  END PROCESS;
189
 
190
  nxt_page_sel_a_dly(0)                   <= page_sel_a;
191
  nxt_page_sel_a_dly(1 TO g_rd_latency-1) <= page_sel_a_dly(0 TO g_rd_latency-2);
192
  nxt_page_sel_b_dly(0)                   <= page_sel_b;
193
  nxt_page_sel_b_dly(1 TO g_rd_latency-1) <= page_sel_b_dly(0 TO g_rd_latency-2);
194
 
195
  p_next_page_a : PROCESS(next_page_a, page_sel_a, page_ofs_a)
196
  BEGIN
197
    nxt_page_sel_a <= page_sel_a;
198
    nxt_page_ofs_a <= page_ofs_a;
199
    IF next_page_a='1' THEN
200
      IF page_sel_a < g_nof_pages-1 THEN
201
        nxt_page_sel_a <= page_sel_a + 1;
202
        nxt_page_ofs_a <= page_ofs_a + g_page_sz;
203
      ELSE
204
        nxt_page_sel_a <= 0;
205
        nxt_page_ofs_a <= 0;
206
      END IF;
207
    END IF;
208
  END PROCESS;
209
 
210
  p_next_page_b : PROCESS(next_page_b, page_sel_b, page_ofs_b)
211
  BEGIN
212
    nxt_page_sel_b <= page_sel_b;
213
    nxt_page_ofs_b <= page_ofs_b;
214
    IF next_page_b='1' THEN
215
      IF page_sel_b < g_nof_pages-1 THEN
216
        nxt_page_sel_b <= page_sel_b + 1;
217
        nxt_page_ofs_b <= page_ofs_b + g_page_sz;
218
      ELSE
219
        nxt_page_sel_b <= 0;
220
        nxt_page_ofs_b <= 0;
221
      END IF;
222
    END IF;
223
  END PROCESS;
224
 
225
 
226
  gen_mux : IF g_str = "use_mux" GENERATE
227
    gen_pages : FOR I IN 0 TO g_nof_pages-1 GENERATE
228
      u_ram : ENTITY work.common_ram_crw_crw
229
      GENERIC MAP (
230
        g_technology     => g_technology,
231
        g_ram            => c_page_ram,
232
        g_init_file      => "UNUSED",
233
        g_true_dual_port => g_true_dual_port
234
      )
235
      PORT MAP (
236
        rst_a     => rst_a,
237
        rst_b     => rst_b,
238
        clk_a     => clk_a,
239
        clk_b     => clk_b,
240
        clken_a   => clken_a,
241
        clken_b   => clken_b,
242
        adr_a     => adr_a,
243
        wr_en_a   => page_wr_en_a(I),
244
        wr_dat_a  => wr_dat_a,
245
        rd_en_a   => page_rd_en_a(I),
246
        rd_dat_a  => page_rd_dat_a(I),
247
        rd_val_a  => page_rd_val_a(I),
248
        adr_b     => adr_b,
249
        wr_en_b   => page_wr_en_b(I),
250
        wr_dat_b  => wr_dat_b,
251
        rd_en_b   => page_rd_en_b(I),
252
        rd_dat_b  => page_rd_dat_b(I),
253
        rd_val_b  => page_rd_val_b(I)
254
      );
255
    END GENERATE;
256
 
257
    p_mux : PROCESS(page_sel_a, wr_en_a, rd_en_a, page_sel_a_dly, page_rd_dat_a, page_rd_val_a,
258
                    page_sel_b, wr_en_b, rd_en_b, page_sel_b_dly, page_rd_dat_b, page_rd_val_b)
259
    BEGIN
260
      -- use page_sel direct for control
261
      page_wr_en_a <= (OTHERS=>'0');
262
      page_wr_en_b <= (OTHERS=>'0');
263
      page_rd_en_a <= (OTHERS=>'0');
264
      page_rd_en_b <= (OTHERS=>'0');
265
      page_wr_en_a(page_sel_a) <= wr_en_a;
266
      page_wr_en_b(page_sel_b) <= wr_en_b;
267
      page_rd_en_a(page_sel_a) <= rd_en_a;
268
      page_rd_en_b(page_sel_b) <= rd_en_b;
269
 
270
      -- use page_sel_dly to account for the RAM read latency
271
      rd_dat_a <= page_rd_dat_a(page_sel_a_dly(g_rd_latency-1));
272
      rd_dat_b <= page_rd_dat_b(page_sel_b_dly(g_rd_latency-1));
273
      rd_val_a <= page_rd_val_a(page_sel_a_dly(g_rd_latency-1));
274
      rd_val_b <= page_rd_val_b(page_sel_b_dly(g_rd_latency-1));
275
    END PROCESS;
276
  END GENERATE;  -- gen_mux
277
 
278
  gen_adr : IF g_str = "use_adr" GENERATE
279
    u_mem : ENTITY work.common_ram_crw_crw
280
    GENERIC MAP (
281
      g_technology     => g_technology,
282
      g_ram            => c_mem_ram,
283
      g_init_file      => "UNUSED",
284
      g_true_dual_port => g_true_dual_port
285
    )
286
    PORT MAP (
287
      rst_a     => rst_a,
288
      rst_b     => rst_b,
289
      clk_a     => clk_a,
290
      clk_b     => clk_b,
291
      clken_a   => clken_a,
292
      clken_b   => clken_b,
293
      adr_a     => mem_adr_a,
294
      wr_en_a   => wr_en_a,
295
      wr_dat_a  => wr_dat_a,
296
      rd_en_a   => rd_en_a,
297
      rd_dat_a  => rd_dat_a,
298
      rd_val_a  => rd_val_a,
299
      adr_b     => mem_adr_b,
300
      wr_en_b   => wr_en_b,
301
      wr_dat_b  => wr_dat_b,
302
      rd_en_b   => rd_en_b,
303
      rd_dat_b  => rd_dat_b,
304
      rd_val_b  => rd_val_b
305
    );
306
 
307
    mem_adr_a <= TO_UVEC(page_sel_a, c_mem_nof_pages_w) & adr_a;
308
    mem_adr_b <= TO_UVEC(page_sel_b, c_mem_nof_pages_w) & adr_b;
309
  END GENERATE;  -- gen_adr
310
 
311
 
312
  gen_ofs : IF g_str = "use_ofs" GENERATE
313
    u_buf : ENTITY work.common_ram_crw_crw
314
    GENERIC MAP (
315
      g_technology     => g_technology,
316
      g_ram            => c_buf_ram,
317
      g_init_file      => "UNUSED",
318
      g_true_dual_port => g_true_dual_port
319
    )
320
    PORT MAP (
321
      rst_a     => rst_a,
322
      rst_b     => rst_b,
323
      clk_a     => clk_a,
324
      clk_b     => clk_b,
325
      clken_a   => clken_a,
326
      clken_b   => clken_b,
327
      adr_a     => buf_adr_a,
328
      wr_en_a   => wr_en_a,
329
      wr_dat_a  => wr_dat_a,
330
      rd_en_a   => rd_en_a,
331
      rd_dat_a  => rd_dat_a,
332
      rd_val_a  => rd_val_a,
333
      adr_b     => buf_adr_b,
334
      wr_en_b   => wr_en_b,
335
      wr_dat_b  => wr_dat_b,
336
      rd_en_b   => rd_en_b,
337
      rd_dat_b  => rd_dat_b,
338
      rd_val_b  => rd_val_b
339
    );
340
 
341
    buf_adr_a <= INCR_UVEC(RESIZE_UVEC(adr_a, c_buf_addr_w), page_ofs_a);
342
    buf_adr_b <= INCR_UVEC(RESIZE_UVEC(adr_b, c_buf_addr_w), page_ofs_b);
343
  END GENERATE;  -- gen_ofs
344
 
345
END rtl;

powered by: WebSVN 2.1.0

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