1--------------------------------------------------------------------------------
2--! @file
3--! @brief A bunch of useful functions for (non)synthesizable  VHDL
4--------------------------------------------------------------------------------
5library ieee;
6    use ieee.std_logic_1164.all;
7    use ieee.numeric_std.all;
8    use ieee.math_real.all;
9library std;
10    use std.textio.all;
11
12package er_pack is
13    -- constants used inside function 'rt'
14    constant simres  : time := 1 ps;    -- simulation resolution (time)
15    constant resreal : real := 1.0e-12; -- simulation resolution (real)
16
17    ----------------------------------------------------------------------------
18    -- Types, Subtypes, and constants
19    ----------------------------------------------------------------------------
20    type integer_vector  is array (integer range <>) of integer;
21    type natural_vector  is array (integer range <>) of natural;
22    type real_vector     is array (integer range <>) of real;
23    ----------------------------------------------------------------------------
24
25    ----------------------------------------------------------------------------
26    -- synthesis off
27    function print_nibble(arg : std_logic_vector(3 downto 0)) return character;
28    function print_message(arg : string) return boolean;
29    -- synthesis on
30
31    ----------------------------------------------------------------------------
32    -- print function
33    ----------------------------------------------------------------------------
34    -- synthesis off
35    function slv2string (arg : in std_logic_vector) return string;
36    -- synthesis on
37
38    ----------------------------------------------------------------------------
39    --! Return a vector of all ones.
40    --! @param arg The number of bits in the output vector.
41    --! @returns A vector of all ones.
42    ----------------------------------------------------------------------------
43    function ones (arg : natural) return std_logic_vector;
44
45    ----------------------------------------------------------------------------
46    --! Return a vector of all zeros.
47    --! @param arg The number of bits in the output vector.
48    --! @returns A vector of all zeros.
49    ----------------------------------------------------------------------------
50    function zeros(arg : natural) return std_logic_vector;
51
52    ----------------------------------------------------------------------------
53    --! Return the maximum (max positive) 2's complement value that can be
54    --! expressed in the given number of bits.  This is defined as {0,1,...,1}.
55    --! @param arg The number of bits in the output vector.
56    --! @returns The maximum 2's complement value.
57    ----------------------------------------------------------------------------
58    function max  (arg : natural) return std_logic_vector;
59
60    ----------------------------------------------------------------------------
61    --! Return the minimum (max negative) 2's complement value that can be
62    --! expressed in the given number of bits.  This is defined as {1,0,...,0}.
63    --! @param arg The number of bits in the output vector.
64    --! @returns The minimum 2's complement value.
65    ----------------------------------------------------------------------------
66    function min  (arg : natural) return std_logic_vector;
67
68    ----------------------------------------------------------------------------
69    --! Return the maximum value of two input values.
70    --! @param a The first input value
71    --! @param b The second input value
72    --! @returns The maximum value of a and b
73    ----------------------------------------------------------------------------
74    function max(a:natural; b:natural) return natural;
75
76    ----------------------------------------------------------------------------
77    --! Return the minimum value of two input values.
78    --! @param a The first input value
79    --! @param b The second input value
80    --! @returns The minimum value of a and b
81    ----------------------------------------------------------------------------
82    function min(a:natural; b:natural) return natural;
83
84    ----------------------------------------------------------------------------
85    --! Return the next multiple of the given variable
86    --! @param arg The input value
87    --! @param mult The multiple
88    --! @returns arg rounded up to the next multiple of mult
89    ----------------------------------------------------------------------------
90    function next_multiple (arg : natural; mult : natural) return natural;
91
92    ----------------------------------------------------------------------------
93    --! Log function
94    --! This might be the single most useful function in all of VHDL.  It simply
95    --! returns the log of a value
96    --! @param base The base to use for the log.
97    --! @param arg The value to log.
98    --! @returns The log (arg)
99    ----------------------------------------------------------------------------
100    function log (base : positive; arg : positive) return natural;
101
102    ----------------------------------------------------------------------------
103    --! Log2 function
104    --! This might be the single most useful function in all of VHDL.  It simply
105    --! returns the log2 of a value
106    --! @param arg The value to log.
107    --! @returns The log2 (arg)
108    ----------------------------------------------------------------------------
109    function log2 (arg : positive) return natural;
110
111    ----------------------------------------------------------------------------
112    --! Number of Bits function
113    --! Return the number of bits necessary to hold a particular values.  This
114    --! is the log2 function rounded up
115    --! @param arg The value to store
116    --! @returns The number of bits necessary to hold arg
117    ----------------------------------------------------------------------------
118    function num_bits (arg : positive) return natural;
119
120    ----------------------------------------------------------------------------
121    --! delay via register
122    --! This function should take place in a clocked process, but is an easy
123    --! way to delay a signal
124    --! @param reg The shift register that is doing the delaying
125    --! @param sig The signal that is being delayed.  This is put in the low
126    --!        address of the signal.
127    --! @returns This will return the shifted (delayed) vector
128    ----------------------------------------------------------------------------
129    function delay (
130        reg : natural_vector;
131        sig : natural) return natural_vector;
132
133    ----------------------------------------------------------------------------
134    --! delay via register
135    --! This function should take place in a clocked process, but is an easy
136    --! way to delay a signal
137    --! @param reg The shift register that is doing the delaying
138    --! @param sig The signal that is being delayed.  This is put in the low
139    --!        address of the signal.
140    --! @returns This will return the shifted (delayed) vector
141    ----------------------------------------------------------------------------
142    function delay (
143        reg : integer_vector;
144        sig : integer) return integer_vector;
145
146    ----------------------------------------------------------------------------
147    --! delay via register
148    --! This function should take place in a clocked process, but is an easy
149    --! way to delay a signal
150    --! @param reg The shift register that is doing the delaying
151    --! @param sig The signal that is being delayed.  This is put in the low
152    --!        address of the signal.
153    --! @returns This will return the shifted (delayed) vector
154    ----------------------------------------------------------------------------
155    function delay (
156        reg : std_logic_vector;
157        sig : std_logic) return std_logic_vector;
158
159    ----------------------------------------------------------------------------
160    --! Return a std_logic that is the result of a rising edge detector.  There
161    --! will need to be an input register with at least two values in it, since
162    --! different indexes are used to derive the output.
163    --! @param reg The input shift/Delay register
164    --! @param idx (Optional) The index of the input reg register to start the
165    --!        the detection.  The default value is the highest most index.
166    --! @return not reg(idx) and reg(idx-1);
167    ----------------------------------------------------------------------------
168    function rising_edge (reg : std_logic_vector; idx : integer) return std_logic;
169    function rising_edge (reg : std_logic_vector)                return std_logic;
170
171    ----------------------------------------------------------------------------
172    --! Return a std_logic that is the result of a falling edge detector.  There
173    --! will need to be an input register with at least two values in it, since
174    --! different indexes are used to derive the output.
175    --! @param reg The input shift/Delay register
176    --! @param idx (Optional) The index of the input reg register to start the
177    --!        the detection.  The default value is the highest most index.
178    --! @return reg(idx) and not reg(idx-1);
179    ----------------------------------------------------------------------------
180    function falling_edge (reg : std_logic_vector; idx : integer) return std_logic;
181    function falling_edge (reg : std_logic_vector)                return std_logic;
182
183    ----------------------------------------------------------------------------
184    --! Return a std_logic that is the result of an edge detector.  There will
185    --! need to be an input register with at least two values in it, since
186    --! different indexes are used to derive the output.
187    --! @param reg The input shift/Delay register
188    --! @param idx (Optional) The index of the input reg register to start the
189    --!        the detection.  The default value is the highest most index.
190    --! @return reg(idx) xor reg(idx-1);
191    ----------------------------------------------------------------------------
192    function edge (reg : std_logic_vector)                return std_logic;
193    function edge (reg : std_logic_vector; idx : integer) return std_logic;
194
195    ----------------------------------------------------------------------------
196    --! Flip a register.  This will put the high bits in the low positions,
197    --! producing a mirror image of the bits.  It will preserve the range of the
198    --! input vector.
199    --! @param ret The input register.
200    --! @return The flipped version of the input register.
201    ----------------------------------------------------------------------------
202    function flip (reg : std_logic_vector) return std_logic_vector;
203
204    ----------------------------------------------------------------------------
205    --! Convert a real number to a std_logic_vector with a given number of bits.
206    --! The input real should be a value between 1.0 and -1.0.  Any value
207    --! outside of this range will saturate the output vector.
208    --! @param l The real number
209    --! @param b The number of bits for the std_logic_vector
210    ----------------------------------------------------------------------------
211    function to_slv(l:real; b:natural) return std_logic_vector;
212
213    ----------------------------------------------------------------------------
214    -- Convert a time to a real representation for the number of seconds
215    -- @param t The time to convert
216    -- @return The real time (in seconds)
217    ----------------------------------------------------------------------------
218    function rt(t : time) return real;
219
220    ----------------------------------------------------------------------------
221    --! Divide two times.  Return a real
222    --! @param l The numerator
223    --! @param r The denominator
224    --! @returns The result of the divide in a real number
225    ----------------------------------------------------------------------------
226    function "/" (l, r : time) return real;
227
228    ----------------------------------------------------------------------------
229    --! Priority decoder
230    --! Return the lowest index that is set high.
231    --! @param reg the register to decode
232    --! @returns The index of the highest bit set.  If the whole register is
233    --!     zero, then it returns an out-of-bound integer
234    ----------------------------------------------------------------------------
235    function priority_decode(reg : std_logic_vector) return integer;
236
237    ----------------------------------------------------------------------------
238    --! Saturate an unsigned value to the given number of bits.
239    --! @param val The unsigned value
240    --! @param bits The number of bits
241    --! @returns If the input value is greater than the requested number of bits
242    --!    can hold, it will return 2^bits-1.  All other cases will return the
243    --!    original number.
244    ----------------------------------------------------------------------------
245    function saturate(val : unsigned; bits : natural) return unsigned;
246    function usat(val : std_logic_vector; bits : natural ) return std_logic_vector;
247
248    ----------------------------------------------------------------------------
249    --! Saturate a signed value to the given number of bits.
250    --! @param val The signed value
251    --! @param bits The number of bits
252    --! @returns If the absolute value of the input value is greater than
253    --! 2^(bits-1)-1, then return the appriate signed version of 2^(bits-1)-1.
254    --!    All other cases will return the original number.
255    ----------------------------------------------------------------------------
256    function saturate(val : signed; bits : natural) return signed;
257    function ssat(val : std_logic_vector; bits : natural ) return std_logic_vector;
258
259    ----------------------------------------------------------------------------
260    --! numeric_std helper functions
261    --! (un)signed shift left/right
262    ----------------------------------------------------------------------------
263    --! unsigned shift left
264    function usl (val : std_logic_vector; bits : natural) return std_logic_vector;
265    --! unsigned shift right
266    function usr (val : std_logic_vector; bits : natural) return std_logic_vector;
267    --! signed shift left
268    function ssl (val : std_logic_vector; bits : natural) return std_logic_vector;
269    --! signed shift right
270    function ssr (val : std_logic_vector; bits : natural) return std_logic_vector;
271
272end package er_pack;
273
274--------------------------------------------------------------------------------
275--------------------------------------------------------------------------------
276-- Package body
277--------------------------------------------------------------------------------
278--------------------------------------------------------------------------------
279package body er_pack is
280    ----------------------------------------------------------------------------
281    -- synthesis off
282    function print_nibble(arg : std_logic_vector(3 downto 0))
283    return character is
284        variable ret : character;
285        variable num : natural;
286        -- status variables
287        variable is_x    : boolean;
288        variable is_u    : boolean;
289        variable is_dash : boolean;
290        variable is_z    : boolean;
291        variable is_w    : boolean;
292    begin
293        for idx in arg'range loop
294            -- take care of the special cases
295            case arg(idx) is
296                when 'X' => is_x    := true;
297                when 'U' => is_u    := true;
298                when '-' => is_dash := true;
299                when 'Z' => is_z    := true;
300                when 'W' => is_w    := true;
301                when others => NULL;
302            end case;
303        end loop;
304
305        -- Print it
306        if    is_x    then ret := 'X';
307        elsif is_u    then ret := 'U';
308        elsif is_dash then ret := '-';
309        elsif is_z    then ret := 'Z';
310        elsif is_w    then ret := 'W';
311        else
312            num := to_integer(unsigned(arg));
313            case num is
314                when 15 =>     ret := 'F';
315                when 14 =>     ret := 'E';
316                when 13 =>     ret := 'D';
317                when 12 =>     ret := 'C';
318                when 11 =>     ret := 'B';
319                when 10 =>     ret := 'A';
320                when  9 =>     ret := '9';
321                when  8 =>     ret := '8';
322                when  7 =>     ret := '7';
323                when  6 =>     ret := '6';
324                when  5 =>     ret := '5';
325                when  4 =>     ret := '4';
326                when  3 =>     ret := '3';
327                when  2 =>     ret := '2';
328                when  1 =>     ret := '1';
329                when  0 =>     ret := '0';
330                when others => ret := 'J';
331            end case;
332        end if;
333
334        -- we're done
335        return ret;
336    end function print_nibble;
337
338    --! Just print a string.  It's not hard, but it takes more than one line
339    --! without the function
340    function print_message(arg : string) return boolean is
341        variable out_line  : line;
342    begin
343        write(out_line, arg);
344        writeline(output, out_line);
345        return true;
346    end function print_message;
347
348    -- print function
349    function slv2string (arg : in std_logic_vector) return string is
350        variable ret : string (1 to arg'length/4+1);
351        variable jdx : integer;
352        variable tmp_nibble : std_logic_vector(3 downto 0);
353        variable kdx : natural := 1;
354    begin
355        -- Try to get a useful hex value
356        jdx := 0;
357        kdx := ret'high;
358        for idx in arg'reverse_range loop
359            -- fill the next value of the nibble
360            tmp_nibble(jdx) := arg(idx);
361
362            -- correct jdx and print accordingly
363            if jdx = 3 then
364                -- reset the jdx value
365                jdx      := 0;
366                ret(kdx) := print_nibble(tmp_nibble);
367
368                -- correct kdx
369                kdx := kdx - 1;
370            else
371                -- decrement jdx
372                jdx := jdx + 1;
373            end if;
374
375        end loop;
376
377        -- edge cases
378        if jdx /= 0 then
379            tmp_nibble(3 downto jdx) := (others => '0');
380            ret(kdx)                 := print_nibble(tmp_nibble);
381            return ret;
382        end if;
383
384        -- if we got here, then we have an exact number of nibbles.  Give back
385        -- all but one character.
386        return ret(2 to ret'high);
387    end function slv2string;
388    -- synthesis on
389
390    ----------------------------------------------------------------------------
391    function ones (arg : natural) return std_logic_vector is
392        variable ret : std_logic_vector(arg-1 downto 0) := (others => '1');
393    begin
394        return ret;
395    end function ones;
396    ----------------------------------------------------------------------------
397    function zeros(arg : natural) return std_logic_vector is
398        variable ret : std_logic_vector(arg-1 downto 0) := (others => '0');
399    begin
400        return ret;
401    end function zeros;
402    ----------------------------------------------------------------------------
403    function max  (arg : natural) return std_logic_vector is
404        variable ret : std_logic_vector(arg-1 downto 0) := '0' & ones(arg-1);
405    begin
406        return ret;
407    end function max;
408    ----------------------------------------------------------------------------
409    function min  (arg : natural) return std_logic_vector is
410        variable ret : std_logic_vector(arg-1 downto 0) := '1' & zeros(arg-1);
411    begin
412        return ret;
413    end function min;
414    ----------------------------------------------------------------------------
415    function max(a:natural; b:natural) return natural is
416    begin
417        if a > b then
418            return a;
419        end if;
420        return b;
421    end function max;
422    ----------------------------------------------------------------------------
423    function min(a:natural; b:natural) return natural is
424    begin
425        if a < b then
426            return a;
427        end if;
428        return b;
429    end function min;
430    ----------------------------------------------------------------------------
431    function next_multiple (arg : natural; mult : natural)
432    return natural is
433    begin
434        return (arg / mult) * mult;
435    end function next_multiple;
436
437    ----------------------------------------------------------------------------
438    function log (base : positive; arg : positive) return natural is
439        variable div : positive := arg;
440        variable ret  : natural  := 0;
441    begin
442        while div > 1 loop
443            div := div / base;
444            ret := ret + 1;
445        end loop;
446        return ret;
447    end function log;
448
449    ----------------------------------------------------------------------------
450    function log2 (arg : positive) return natural is
451    begin
452        return log(2, arg);
453    end function log2;
454
455    ----------------------------------------------------------------------------
456    function num_bits (arg : positive) return natural is
457        variable ret : natural := log2(arg);
458    begin
459        if 2**ret /= arg then
460            ret := ret + 1;
461        end if;
462        return ret;
463    end function num_bits;
464
465    ----------------------------------------------------------------------------
466    function delay (
467        reg : integer_vector;
468        sig : integer)
469    return integer_vector is
470        variable ret : integer_vector(reg'range);
471    begin
472        if ret'ascending then
473            ret := sig & reg(reg'low to reg'high-1);
474        else
475            ret := reg(reg'high-1 downto reg'low) & sig;
476        end if;
477        return ret;
478    end function;
479
480    function delay (
481        reg : natural_vector;
482        sig : natural)
483    return natural_vector is
484        variable ret : natural_vector(reg'range);
485    begin
486        if ret'ascending then
487            ret := sig & reg(reg'low to reg'high-1);
488        else
489            ret := reg(reg'high-1 downto reg'low) & sig;
490        end if;
491        return ret;
492    end function;
493
494    function delay (
495        reg : std_logic_vector;
496        sig : std_logic)
497    return std_logic_vector is
498        variable ret : std_logic_vector(reg'range);
499    begin
500        if ret'ascending then
501            ret := sig & reg(reg'low to reg'high-1);
502        else
503            ret := reg(reg'high-1 downto reg'low) & sig;
504        end if;
505        return ret;
506    end function;
507
508    ----------------------------------------------------------------------------
509    function rising_edge (
510        reg : std_logic_vector)
511    return std_logic is
512        variable idx : integer := reg'high;
513    begin
514        return rising_edge(reg, idx);
515    end function;
516    ----------------------------------------------------------------------------
517    function rising_edge (
518        reg : std_logic_vector;
519        idx : integer)
520    return std_logic is
521    begin
522        -- Check the input for validity
523        assert reg'length >= 2
524            report "input vector not long enough" severity error;
525        assert idx <= reg'high and idx > reg'low
526            report "input vector not long enough" severity error;
527
528        -- now just return the answer
529        return not reg(idx) and reg(idx-1);
530    end function;
531    ----------------------------------------------------------------------------
532    function falling_edge (
533        reg : std_logic_vector)
534    return std_logic is
535        variable idx : integer := reg'high;
536    begin
537        return falling_edge(reg, idx);
538    end function falling_edge;
539    ----------------------------------------------------------------------------
540    function falling_edge (
541        reg : std_logic_vector;
542        idx : integer)
543    return std_logic is
544    begin
545        -- Check the input for validity
546        assert reg'length >= 2
547            report "input vector not long enough" severity error;
548        assert idx <= reg'high and idx > reg'low
549            report "input vector not long enough" severity error;
550
551        -- now just return the answer
552        return reg(idx) and not reg(idx-1);
553    end function falling_edge;
554    ----------------------------------------------------------------------------
555    function edge (
556        reg : std_logic_vector)
557    return std_logic is
558        variable idx : integer := reg'high;
559    begin
560        return edge(reg, idx);
561    end function edge;
562    ----------------------------------------------------------------------------
563    function edge (
564        reg : std_logic_vector;
565        idx : integer)
566    return std_logic is
567    begin
568        -- Check the input for validity
569        assert reg'length >= 2
570            report "input vector not long enough" severity error;
571        assert idx <= reg'high and idx > reg'low
572            report "input vector not long enough" severity error;
573
574        -- now just return the answer
575        return reg(idx) xor reg(idx-1);
576    end function edge;
577    ----------------------------------------------------------------------------
578    function flip (reg : std_logic_vector) return std_logic_vector is
579        variable ret : std_logic_vector(reg'range);
580        variable idx : integer := reg'high;
581        variable jdx : integer := reg'low;
582    begin
583        while jdx < idx loop
584            -- Populate ret with the reg bits backwards
585            ret(idx) := reg(jdx);
586            ret(jdx) := reg(idx);
587
588            -- update the counters
589            idx := idx + 1;
590            jdx := jdx + 1;
591        end loop;
592
593        -- return the flipped register
594        return ret;
595    end function flip;
596
597    ----------------------------------------------------------------------------
598    function to_slv(l:real; b:natural) return std_logic_vector is
599        variable slv    : std_logic_vector(b-1 downto 0);
600        variable temp_r : real;
601        variable temp_i : integer;
602    begin
603        -- Check the bounds and saturate when necessary
604        if l <= -1.0 then
605            slv := min(b);
606        elsif l >= 1.0 then
607            slv := max(b);
608        else
609            -- Compute the answer
610            temp_r := l * real(2**(b-1)-1);   -- Scale the real to not overflow
611            temp_i := integer(round(temp_r)); -- round it and turn it into an integer
612            slv    := std_logic_vector(to_signed(temp_i, b)); -- Turn it to an slv
613        end if;
614
615        -- Now just return it
616        return slv;
617    end function to_slv;
618
619    ----------------------------------------------------------------------------
620    function rt(t : time) return real is
621        variable nat_time  : natural := t / simres;
622        variable real_time : real    := real(nat_time);
623    begin
624        return real_time * resreal;
625    end;
626
627    ----------------------------------------------------------------------------
628    function "/" (l, r : time) return real is
629        variable real_l : real := rt(l);
630        variable real_r : real := rt(r);
631    begin
632        return real_l / real_r;
633    end function "/";
634
635    ----------------------------------------------------------------------------
636    function priority_decode(reg : std_logic_vector) return integer is
637        variable ret : integer;
638    begin
639        -- Start with the default value
640        if reg'ascending then
641            ret := reg'right + 1;
642        else
643            ret := reg'right - 1;
644        end if;
645
646        -- now determine which one is lit
647        for idx in reg'reverse_range loop
648            if reg(idx) = '1' then
649                ret := idx;
650            end if;
651        end loop;
652
653        -- return it
654        return ret;
655    end function priority_decode;
656
657    ----------------------------------------------------------------------------
658    function saturate(val : unsigned; bits : natural) return unsigned is
659        variable max_val : unsigned(bits-1 downto 0) := unsigned(ones(bits));
660    begin
661        -- Check the value over the max
662        if val > max_val then
663            return resize(max_val, val'length);
664        end if;
665
666        -- If we got here, we just return the value
667        return val;
668    end function saturate;
669
670    -- The std_logic_vector version
671    function usat(val : std_logic_vector; bits : natural ) return std_logic_vector is
672    begin
673        return std_logic_vector(saturate(unsigned(val), bits));
674    end function usat;
675
676    ----------------------------------------------------------------------------
677    function saturate(val : signed; bits : natural) return signed is
678        variable max_val : signed(bits-1 downto 0) := '0' & signed(ones (bits-2)) & '1';
679        variable min_val : signed(bits-1 downto 0) := '1' & signed(zeros(bits-2)) & '1';
680    begin
681        -- Check the value over the max
682        if val > max_val then
683            return resize(max_val, val'length);
684        elsif val < min_val then
685            return resize(min_val, val'length);
686        end if;
687
688        -- If we got here, we just return the value
689        return val;
690    end function saturate;
691
692    -- The std_logic_vector version
693    function ssat(val : std_logic_vector; bits : natural ) return std_logic_vector is
694    begin
695        return std_logic_vector(saturate(signed(val), bits));
696    end function ssat;
697
698    ----------------------------------------------------------------------------
699    -- numeric_std helper functions
700    ----------------------------------------------------------------------------
701    function usl (val : std_logic_vector; bits : natural) return std_logic_vector is
702    begin
703        return std_logic_vector(shift_left(unsigned(val), bits));
704    end function usl;
705    function usr (val : std_logic_vector; bits : natural) return std_logic_vector is
706    begin
707        return std_logic_vector(shift_right(unsigned(val), bits));
708    end function usr;
709    function ssl (val : std_logic_vector; bits : natural) return std_logic_vector is
710    begin
711        return std_logic_vector(shift_left(signed(val), bits));
712    end function ssl;
713    function ssr (val : std_logic_vector; bits : natural) return std_logic_vector is
714    begin
715        return std_logic_vector(shift_right(signed(val), bits));
716    end function ssr;
717end package body;
718
719
720