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

powered by: WebSVN 2.1.0

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