1 -------------------------------------------------------------------------------
2 -- Filename: dynamic_shift_reg.vhd
3 --
4 -- Description: This module implements a dynamic shift register with clock
5 -- enable. (Think, for example, of the function of the SRL16E.)
6 -- The width and depth of the shift register are selectable
7 -- via generics C_DWIDTH and C_DEPTH, respectively.
8 --
9 -- There is no restriction on the values of C_WIDTH and
10 -- C_DEPTH and, in particular, the C_DEPTH does not have
11 -- to be a power of two.
12 --
13 -- if is_power_of_2( C_DEPTH ) then An inferred implementation is used
14 --
15 -- This version allows the client to specify the initial value
16 -- of the contents of the shift register, as applied
17 -- during configuration.
18 --
19 --
20 -- VHDL-Standard: VHDL'93
21 --------------------------------------------------------------------------------
22 -- C_DWIDTH
23 --------------------------------------------------------------------------------
24 -- Theoretically, C_DWIDTH may be set to zero and this could be a more
25 -- natural or preferrable way of excluding a dynamic shift register
26 -- in a client than using a VHDL Generate statement. However, this usage is not
27 -- tested, and the user should expect that some VHDL tools will be deficient
28 -- with respect to handling this properly.
29 --
30 --------------------------------------------------------------------------------
31 -- C_INIT_VALUE
32 --------------------------------------------------------------------------------
33 -- C_INIT_VALUE can be used to specify the initial values of the elements
34 -- in the dynamic shift register, the values to be present after configuration.
35 -- C_INIT_VALUE need not be the same size as the dynamic shift register,
36 --
37 -- Please note that the shift register is not resettable after configuration !!
38 --
39 --------------------------------------------------------------------------------
40 -- A
41 --------------------------------------------------------------------------------
42 -- A addresses the elements of the dynamic shift register.
43 -- A=0 causes the most recently shifted-in element to appear at Dout,
44 -- A=1 the second most recently shifted in element, etc.
45 --------------------------------------------------------------------------------
46
47 library IEEE;
48 use IEEE.std_logic_1164.all;
49 use IEEE.std_logic_unsigned.all;
50
51 -- Uncomment the following library declaration if using
52 -- arithmetic functions with Signed or Unsigned values
53 use ieee.numeric_std.all;
54
55 -- Uncomment the following library declaration if instantiating
56 -- any Xilinx primitives in this code.
57 --library UNISIM;
58 --use UNISIM.VComponents.all;
59
60 use work.my_func_pack.all;
61
62 entity dynamic_shift_reg is
63 generic (
64 C_DEPTH : positive := 32; -- power_of_2(x)
65 C_DWIDTH : natural := 8;
66 C_INIT_VALUE : bit_vector := "0");
67 port(
68 CLK : in std_logic;
69 CE : in std_logic;
70 A : in std_logic_vector(0 to clog2(C_DEPTH)-1);
71 D : in std_logic_vector(0 to C_DWIDTH-1);
72 Q : out std_logic_vector(0 to C_DWIDTH-1);
73 Qn : out std_logic_vector(0 to C_DWIDTH-1));
74 end dynamic_shift_reg;
75
76 architecture rtl of dynamic_shift_reg is
77
78 type shift_reg_type is array (0 to C_DEPTH-1) of std_logic_vector(0 to C_DWIDTH-1);
79
80 ------------------------------------------------------------------------------
81 -- Function used to establish the full initial value.
82 ------------------------------------------------------------------------------
83 function full_initial_value( DWIDTH : natural; DEPTH : positive; INIT_VALUE : bit_vector )
84 return bit_vector is
85 variable r : bit_vector(0 to DWIDTH*DEPTH-1);
86 variable i, j : natural;
87 -- i - the index where filling of r continues
88 -- j - the amount to fill on the cur. iteration of the while loop
89 begin
90 if DWIDTH = 0 then
91 null; -- Handle the case where the shift reg width is zero
92 elsif INIT_VALUE'length = 0 then
93 r := (others => '0');
94 else
95 i := 0;
96 while i /= r'length loop
97 j := min2(INIT_VALUE'length, r'length-i);
98 r(i to i+j-1) := INIT_VALUE(0 to j-1);
99 i := i+j;
100 end loop;
101 end if;
102 return r;
103 end full_initial_value;
104
105 constant FULL_INIT_VAL : bit_vector(0 to C_DWIDTH*C_DEPTH -1)
106 := full_initial_value(C_DWIDTH, C_DEPTH, C_INIT_VALUE);
107
108 function fill_initial_value(DWIDTH : natural; DEPTH : positive; INIT_VAL : bit_vector)
109 return shift_reg_type is
110 variable r : shift_reg_type;
111 begin
112 for i in 0 to DEPTH-1 loop
113 for j in 0 to DWIDTH-1 loop
114 r(i)(j) := bv2sl(INIT_VAL(i*DWIDTH+j));
115 end loop;
116 end loop;
117 return r;
118 end fill_initial_value;
119
120 -- initial value of the contents of the shift register, as applied during configuration.
121 signal shift_reg : shift_reg_type := fill_initial_value(C_DWIDTH, C_DEPTH, FULL_INIT_VAL);
122
123 begin
124
125 process ( clk )
126 begin
127 if rising_edge( clk ) then
128 if CE = '1' then
129 shift_reg <= D & shift_reg( 0 to C_DEPTH-2);
130 end if;
131 end if;
132 end process;
133 Q <= shift_reg(TO_INTEGER(UNSIGNED(A))); -- when (TO_INTEGER(UNSIGNED(A)) < C_DEPTH) else (others => '-');
134 Qn <= shift_reg(C_DEPTH-1);
135
136 end rtl;