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 3

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

powered by: WebSVN 2.1.0

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