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 is110 variable r : shift_reg_type;111 begin112 for i in 0 to DEPTH-1 loop113 for j in 0 to DWIDTH-1 loop114 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 begin124 125 process ( clk )126 begin127 if rising_edge( clk ) then128 if CE = '1' then129 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;