dynamic_shift_reg SRL16E

  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;
posted @ 2012-05-10 13:55  IAmAProgrammer  阅读(445)  评论(0编辑  收藏  举报