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

Subversion Repositories astron_mm

[/] [astron_mm/] [trunk/] [common_field_pkg.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) 2013
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
LIBRARY IEEE, common_pkg_lib;
23
USE IEEE.STD_LOGIC_1164.ALL;
24
USE IEEE.NUMERIC_STD.ALL;
25
USE common_pkg_lib.common_pkg.ALL;
26
USE common_pkg_lib.common_str_pkg.ALL;
27
 
28
-- Purpose:
29
-- . Dynamically map record-like field structures onto SLVs.
30
-- Description:
31
-- . The MM register is defined by mm_fields.vhd.
32
-- . The MM register consists of "RO" = input fields (status) and "RW" = output fields (control) in
33
--   arbitrary order. The entire register is kept in a word_arr slv. The functions can extract the
34
--   "RO" fields into a slv_in and the "RW" fields into a slv_out. Hence the slv_in'LENGTH +
35
--   slv_out'LENGTH = word_arr'LENGTH.
36
--
37
-- . Advantages:
38
--   . Replaces non-generic (dedicated) records;
39
--   . Field widths are variable
40
-- Remarks:
41
 
42
 
43
PACKAGE common_field_pkg IS
44
 
45
  CONSTANT c_common_field_name_len    : NATURAL := 64;
46
  CONSTANT c_common_field_default_len : NATURAL := 256;
47
 
48
  TYPE t_common_field IS RECORD
49
    name     : STRING(1 TO c_common_field_name_len);
50
    mode     : STRING(1 TO 2);
51
    size     : POSITIVE;
52
    default  : STD_LOGIC_VECTOR(c_common_field_default_len-1 DOWNTO 0);
53
  END RECORD;
54
 
55
  TYPE t_common_field_arr IS ARRAY(INTEGER RANGE <>) OF t_common_field;
56
 
57
  FUNCTION field_name_pad(name: STRING) RETURN STRING;
58
 
59
  FUNCTION field_default(slv_in: STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
60
  FUNCTION field_default(nat_in: NATURAL) RETURN STD_LOGIC_VECTOR;
61
 
62
  FUNCTION field_map_defaults(field_arr : t_common_field_arr) RETURN STD_LOGIC_VECTOR;  -- returns slv_out
63
 
64
  FUNCTION field_mode        (field_arr : t_common_field_arr; name: STRING     ) RETURN STRING;
65
  FUNCTION field_size        (field_arr : t_common_field_arr; name: STRING     ) RETURN NATURAL;
66
  FUNCTION field_hi          (field_arr : t_common_field_arr; name: STRING     ) RETURN INTEGER;
67
  FUNCTION field_hi          (field_arr : t_common_field_arr; index: NATURAL   ) RETURN NATURAL;
68
  FUNCTION field_lo          (field_arr : t_common_field_arr; name: STRING     ) RETURN NATURAL;
69
  FUNCTION field_lo          (field_arr : t_common_field_arr; index: NATURAL   ) RETURN NATURAL;
70
  FUNCTION field_slv_len     (field_arr : t_common_field_arr                   ) RETURN NATURAL;
71
  FUNCTION field_slv_in_len  (field_arr : t_common_field_arr                   ) RETURN NATURAL;
72
  FUNCTION field_slv_out_len (field_arr : t_common_field_arr                   ) RETURN NATURAL;
73
  FUNCTION field_nof_words   (field_arr : t_common_field_arr; word_w : NATURAL ) RETURN NATURAL;
74
  FUNCTION field_map_in      (field_arr : t_common_field_arr; slv        : STD_LOGIC_VECTOR; word_w : NATURAL ; mode : STRING) RETURN STD_LOGIC_VECTOR;  -- returns word_arr
75
  FUNCTION field_map_out     (field_arr : t_common_field_arr; word_arr   : STD_LOGIC_VECTOR; word_w : NATURAL                ) RETURN STD_LOGIC_VECTOR;  -- returns slv_out
76
  FUNCTION field_map         (field_arr : t_common_field_arr; word_arr_in: STD_LOGIC_VECTOR; word_arr_out: STD_LOGIC_VECTOR; word_w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- returns word_arr
77
 
78
  FUNCTION field_ovr_arr(field_arr : t_common_field_arr; ovr_init: STD_LOGIC_VECTOR) RETURN t_common_field_arr;
79
 
80
  FUNCTION field_exists(field_arr : t_common_field_arr; name: STRING) RETURN BOOLEAN;
81
 
82
  FUNCTION field_arr_set_mode(field_arr : t_common_field_arr; mode : STRING) RETURN t_common_field_arr;
83
 
84
  FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_common_field_arr ) RETURN t_common_field_arr;
85
 
86
END common_field_pkg;
87
 
88
 
89
PACKAGE BODY common_field_pkg IS
90
 
91
  FUNCTION field_name_pad(name: STRING) RETURN STRING IS
92
  BEGIN
93
    RETURN pad(name, c_common_field_name_len, ' ');
94
  END field_name_pad;
95
 
96
  FUNCTION field_default(slv_in: STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
97
  BEGIN
98
    RETURN RESIZE_UVEC(slv_in, c_common_field_default_len);
99
  END field_default;
100
 
101
  FUNCTION field_default(nat_in: NATURAL) RETURN STD_LOGIC_VECTOR IS
102
  BEGIN
103
    RETURN TO_UVEC(nat_in, c_common_field_default_len);
104
  END field_default;
105
 
106
  FUNCTION field_map_defaults(field_arr : t_common_field_arr) RETURN STD_LOGIC_VECTOR IS
107
    VARIABLE v_slv_out : STD_LOGIC_VECTOR(field_slv_out_len(field_arr)-1 DOWNTO 0);
108
  BEGIN
109
    FOR f IN 0 TO field_arr'HIGH LOOP
110
      IF field_arr(f).mode="RW" THEN
111
        v_slv_out( field_hi(field_arr, field_arr(f).name) DOWNTO field_lo(field_arr, field_arr(f).name)) := field_arr(f).default(field_arr(f).size-1 DOWNTO 0);
112
      END IF;
113
    END LOOP;
114
    RETURN v_slv_out;
115
  END field_map_defaults;
116
 
117
  FUNCTION field_mode(field_arr : t_common_field_arr; name: STRING) RETURN STRING IS
118
  -- Returns the mode string of the passed (via name) field
119
  BEGIN
120
    IF field_exists(field_arr, name) THEN
121
      FOR i IN 0 TO field_arr'HIGH LOOP
122
        IF field_arr(i).name=field_name_pad(name) THEN
123
          RETURN field_arr(i).mode;
124
        END IF;
125
      END LOOP;
126
    ELSE
127
      RETURN "-1";
128
    END IF;
129
  END field_mode;
130
 
131
  FUNCTION field_size(field_arr : t_common_field_arr; name: STRING) RETURN NATURAL IS
132
  -- Returns the size of the passed (via name) field
133
  BEGIN
134
    FOR i IN 0 TO field_arr'HIGH LOOP
135
      IF field_arr(i).name=field_name_pad(name) THEN
136
        RETURN field_arr(i).size;
137
      END IF;
138
    END LOOP;
139
  END field_size;
140
 
141
  FUNCTION field_hi(field_arr : t_common_field_arr; name: STRING) RETURN INTEGER IS
142
  -- Returns the high (=left) bit range index of the field within the field_arr interpreted as concatenated IN or OUT SLV
143
    VARIABLE v_acc_hi : NATURAL := 0;
144
  BEGIN
145
    IF field_exists(field_arr, name) THEN
146
      FOR i IN 0 TO field_arr'HIGH LOOP
147
        IF field_arr(i).mode=field_mode(field_arr, name) THEN  -- increment index only for the "RO" = IN or the "RW" = OUT
148
          v_acc_hi := v_acc_hi + field_arr(i).size;
149
          IF field_arr(i).name = field_name_pad(name) THEN
150
            RETURN v_acc_hi-1;
151
          END IF;
152
        END IF;
153
      END LOOP;
154
    ELSE --field does not exist; return -1 which results in null array
155
      RETURN -1;
156
    END IF;
157
  END field_hi;
158
 
159
  FUNCTION field_hi(field_arr : t_common_field_arr; index : NATURAL) RETURN NATURAL IS
160
  -- Returns the high (=left) bit range index of the field within the field_arr interpreted as concatenated SLV
161
    VARIABLE v_acc_hi : NATURAL := 0;
162
  BEGIN
163
    FOR i IN 0 TO index LOOP
164
      v_acc_hi := v_acc_hi + field_arr(i).size;
165
      IF i = index THEN
166
        RETURN v_acc_hi-1;
167
      END IF;
168
    END LOOP;
169
  END field_hi;
170
 
171
  FUNCTION field_lo(field_arr : t_common_field_arr; name: STRING) RETURN NATURAL IS
172
  -- Returns the low (=right) bit range index of the field within the field_arr interpreted as concatenated IN or OUT SLV
173
    VARIABLE v_acc_hi : NATURAL := 0;
174
  BEGIN
175
    IF field_exists(field_arr, name) THEN
176
      FOR i IN 0 TO field_arr'HIGH LOOP
177
        IF field_arr(i).mode=field_mode(field_arr, name) THEN  -- increment index only for the "RO" = IN or the "RW" = OUT
178
          v_acc_hi := v_acc_hi + field_arr(i).size;
179
          IF field_arr(i).name = field_name_pad(name) THEN
180
            RETURN v_acc_hi-field_arr(i).size;
181
          END IF;
182
        END IF;
183
      END LOOP;
184
    ELSE
185
      RETURN 0;
186
    END IF;
187
  END field_lo;
188
 
189
  FUNCTION field_lo(field_arr : t_common_field_arr; index : NATURAL) RETURN NATURAL IS
190
  -- Returns the low (=right) bit range index of the field within the field_arr interpreted as concatenated SLV
191
    VARIABLE v_acc_hi : NATURAL := 0;
192
  BEGIN
193
    FOR i IN 0 TO index LOOP
194
      v_acc_hi := v_acc_hi + field_arr(i).size;
195
      IF i = index THEN
196
        RETURN v_acc_hi-field_arr(i).size;
197
      END IF;
198
    END LOOP;
199
  END field_lo;
200
 
201
  FUNCTION field_slv_len(field_arr : t_common_field_arr) RETURN NATURAL IS
202
  -- Return the total length of all fields in field_arr
203
    VARIABLE v_len : NATURAL := 0;
204
  BEGIN
205
    FOR i IN 0 TO field_arr'HIGH LOOP
206
      v_len := v_len + field_arr(i).size;
207
    END LOOP;
208
    RETURN v_len;
209
  END field_slv_len;
210
 
211
  FUNCTION field_slv_in_len(field_arr : t_common_field_arr) RETURN NATURAL IS
212
  -- Return the total length of the input fields in field_arr (= all "RO")
213
    VARIABLE v_len : NATURAL := 0;
214
  BEGIN
215
    FOR f IN 0 TO field_arr'HIGH LOOP
216
      IF field_arr(f).mode="RO" THEN
217
        v_len := v_len + field_arr(f).size;
218
      END IF;
219
    END LOOP;
220
    RETURN v_len;
221
  END field_slv_in_len;
222
 
223
  FUNCTION field_slv_out_len(field_arr : t_common_field_arr) RETURN NATURAL IS
224
  -- Return the total length of the output fields in field_arr (= all "RW")
225
    VARIABLE v_len : NATURAL := 0;
226
  BEGIN
227
    FOR f IN 0 TO field_arr'HIGH LOOP
228
      IF field_arr(f).mode="RW" THEN
229
        v_len := v_len + field_arr(f).size;
230
      END IF;
231
    END LOOP;
232
    RETURN v_len;
233
  END field_slv_out_len;
234
 
235
  FUNCTION field_nof_words(field_arr : t_common_field_arr; word_w : NATURAL) RETURN NATURAL IS
236
  -- Return the number of words (of width word_w) required to hold field_arr
237
    VARIABLE v_word_cnt      : NATURAL := 0;
238
    VARIABLE v_nof_reg_words : NATURAL;
239
  BEGIN
240
    FOR f IN 0 TO field_arr'HIGH LOOP
241
      -- Get the number of register words this field spans
242
      v_nof_reg_words := ceil_div(field_arr(f).size, word_w);
243
      FOR w IN 0 TO v_nof_reg_words-1 LOOP
244
        v_word_cnt := v_word_cnt +1;
245
      END LOOP;
246
    END LOOP;
247
    RETURN v_word_cnt;
248
  END field_nof_words;
249
 
250
  FUNCTION field_map_in(field_arr : t_common_field_arr; slv: STD_LOGIC_VECTOR; word_w : NATURAL; mode : STRING) RETURN STD_LOGIC_VECTOR IS
251
  -- Re-map a field SLV into a larger SLV, support mapping both the slv_in or the slv_out that dependents on mode; each field starting at a word boundary (word_w)
252
    VARIABLE v_word_arr : STD_LOGIC_VECTOR(field_nof_words(field_arr, word_w)*word_w-1 DOWNTO 0) := (OTHERS=>'0');
253
    VARIABLE v_word_cnt : NATURAL := 0;
254
  BEGIN
255
    FOR f IN 0 TO field_arr'HIGH LOOP
256
       -- Only extract the fields that are inputs
257
      IF field_arr(f).mode=mode THEN  -- if mode="RO" then slv = slv_in, else if mode="RW" then slv = slv_out
258
        -- Extract the field 
259
        v_word_arr( v_word_cnt*word_w+field_arr(f).size-1 DOWNTO v_word_cnt*word_w) := slv( field_hi(field_arr, field_arr(f).name) DOWNTO field_lo(field_arr, field_arr(f).name) );
260
      END IF;
261
      -- Calculate the correct word offset for the next field
262
      v_word_cnt  := v_word_cnt + ceil_div(field_arr(f).size, word_w);
263
    END LOOP;
264
    RETURN v_word_arr;
265
  END field_map_in;
266
 
267
  FUNCTION field_map_out(field_arr : t_common_field_arr; word_arr: STD_LOGIC_VECTOR; word_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
268
  -- Reverse of field_map_in
269
    VARIABLE v_slv_out  : STD_LOGIC_VECTOR(field_slv_out_len(field_arr)-1 DOWNTO 0) := (OTHERS=>'0');
270
    VARIABLE v_word_cnt : NATURAL := 0;
271
  BEGIN
272
    FOR f IN 0 TO field_arr'HIGH LOOP
273
      -- Only extract the fields that are outputs 
274
      IF field_arr(f).mode="RW" THEN
275
        -- Extract the field 
276
        v_slv_out( field_hi(field_arr, field_arr(f).name) DOWNTO field_lo(field_arr, field_arr(f).name)) := word_arr( v_word_cnt*word_w+field_arr(f).size-1 DOWNTO v_word_cnt*word_w);
277
      END IF;
278
      -- Calculate the correct word offset for the next field
279
      v_word_cnt  := v_word_cnt + ceil_div(field_arr(f).size, word_w);
280
    END LOOP;
281
    RETURN v_slv_out;
282
  END field_map_out;
283
 
284
  FUNCTION field_map(field_arr : t_common_field_arr; word_arr_in: STD_LOGIC_VECTOR; word_arr_out: STD_LOGIC_VECTOR; word_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
285
  -- Create one SLV consisting of both read-only and output-readback fields, e.g. as input to an MM reg
286
    VARIABLE v_word_arr : STD_LOGIC_VECTOR(field_nof_words(field_arr, word_w)*word_w-1 DOWNTO 0);
287
    VARIABLE v_word_cnt : NATURAL := 0;
288
  BEGIN
289
    -- Wire the entire SLV to the input SLV by default
290
    v_word_arr := word_arr_in;
291
    -- Now re-assign the words that need to be read back from word_arr_out
292
    FOR f IN 0 TO field_arr'HIGH LOOP
293
      IF field_arr(f).mode="RW" THEN
294
        v_word_arr( v_word_cnt*word_w+field_arr(f).size-1 DOWNTO v_word_cnt*word_w):= word_arr_out( v_word_cnt*word_w+field_arr(f).size-1 DOWNTO v_word_cnt*word_w);
295
      END IF;
296
      -- Calculate the correct word offset for the next field
297
      v_word_cnt := v_word_cnt + ceil_div(field_arr(f).size, word_w);
298
    END LOOP;
299
    RETURN v_word_arr;
300
  END field_map;
301
 
302
  FUNCTION field_ovr_arr(field_arr : t_common_field_arr; ovr_init: STD_LOGIC_VECTOR) RETURN t_common_field_arr IS
303
  -- Copy field_arr but change widths to 1 to create a 1-bit override field for each field in field_arr.
304
    VARIABLE v_ovr_field_arr : t_common_field_arr(field_arr'RANGE);
305
  BEGIN
306
    v_ovr_field_arr:= field_arr;
307
    FOR i IN field_arr'RANGE LOOP
308
      v_ovr_field_arr(i).size := 1;
309
      v_ovr_field_arr(i).default := field_default(slv(ovr_init(i)));
310
    END LOOP;
311
    RETURN v_ovr_field_arr;
312
  END field_ovr_arr;
313
 
314
  FUNCTION field_exists(field_arr : t_common_field_arr; name: STRING) RETURN BOOLEAN IS
315
  BEGIN
316
    FOR i IN field_arr'RANGE LOOP
317
      IF field_arr(i).name=field_name_pad(name) THEN
318
        RETURN TRUE;
319
      END IF;
320
    END LOOP;
321
  RETURN FALSE;
322
  END field_exists;
323
 
324
  FUNCTION field_arr_set_mode(field_arr : t_common_field_arr; mode : STRING) RETURN t_common_field_arr IS
325
    VARIABLE v_field_arr : t_common_field_arr(field_arr'RANGE);
326
  BEGIN
327
    v_field_arr := field_arr;
328
    FOR i IN field_arr'RANGE LOOP
329
      v_field_arr(i).mode := mode;
330
    END LOOP;
331
    RETURN v_field_arr;
332
  END field_arr_set_mode;
333
 
334
  FUNCTION sel_a_b(sel :BOOLEAN; a, b : t_common_field_arr) RETURN t_common_field_arr IS
335
  BEGIN
336
    IF sel = TRUE THEN
337
      RETURN a;
338
    ELSE
339
      RETURN b;
340
    END IF;
341
  END;
342
 
343
END common_field_pkg;

powered by: WebSVN 2.1.0

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