------------------------------------------------- -- lfsr_generic.vhd -- -- Revised 2001/02/09 -- -- Authors: Raymond Sung -- Date: Oct 10, 2000 -- Course: EE552 -- Modified: John Koob & Ray Sung -- Source: EE 552 Student Application Note -- Desc: -- -- Autononmous Linear Feedback Shift Register -- -- Description: Implementation of a Linear Feedback Shift Register -- that generates a sequence of 2^N-1 non-repeating pseudo-random numbers. -- -- The Bit-Width or Length of the Pseudo Random Sequence -- can be instantiated with the generic "Width." -- -- The length of the pseudorandom sequence can be anywhere from 2 to 16. -- (2^2 = 4 numbers in sequence and 2^16 numbers sequence !! -- -- The seed input variable allows one to start the pseudo-random sequence at -- a certain position in the pseudo-random sequence. -- -- Uses: Digital Signal Processing -- Wireless Communications -- Encryption/Decryption -- Direct Sequence Spread Spectrum -- Pseudo-Random Number Generation -- Scrambler/Descrambler -- Built-In Self Test -- -- References: "HDL Chip Design" - Douglas J. Smith -- "Linear Feedback Shift Register MegaFunction" - Nova Engineering library IEEE; use IEEE.STD_Logic_1164.all; entity LFSR_GENERIC is generic(Width: positive := 4); -- length of pseudo-random sequence port ( clock: in std_logic; reset: in std_logic; -- active high reset load: in std_logic; -- active high load (assert this to use as regular reg) enable: in std_logic; -- active high enable parallel_in: in std_logic_vector(Width-1 downto 0); -- parallel seed input parallel_out: out std_logic_vector(Width-1 downto 0); -- parallel data out serial_out: out std_logic -- serial data out (From last shift register) ); end entity LFSR_GENERIC; architecture RTL of LFSR_GENERIC is type TapsArrayType is array(2 to 16) of std_logic_vector(15 downto 0); signal Taps: std_logic_vector(Width-1 downto 0); begin LFSR: process (clock) -- internal registers and signals variable LFSR_Reg: std_logic_vector(Width-1 downto 0); variable XOR_Out: std_logic_vector(Width-2 downto 0); variable OR_Chain: std_logic_vector(Width-2 downto 0); variable NOR_All: std_logic; variable Feedback: std_logic; variable TapsArray: TapsArrayType; begin Taps <= TapsArray(Width)(Width-1 downto 0); -- get tap points from lookup table if reset='1' then LFSR_Reg := (others=>'1'); OR_Chain := (others=>'0'); Feedback := '0'; NOR_All := '0'; -- Look-Up Table for Tap points to insert XOR gates as feedback into D-FF -- outputs. Taps are designed so that 2^N-1 (N=Width of Register) numbers -- are cycled through before the sequence is repeated TapsArray(2) := "0000000000000011"; TapsArray(3) := "0000000000000101"; TapsArray(4) := "0000000000001001"; TapsArray(5) := "0000000000010010"; TapsArray(6) := "0000000000100001"; TapsArray(7) := "0000000001000001"; TapsArray(8) := "0000000010001110"; TapsArray(9) := "0000000100001000"; TapsArray(10) := "0000001000000100"; TapsArray(11) := "0000010000000010"; TapsArray(12) := "0000100000101001"; TapsArray(13) := "0001000000001101"; TapsArray(14) := "0010000000010101"; TapsArray(15) := "0100000000000001"; TapsArray(16) := "1000000000010110"; elsif rising_edge(clock) then -- load signal asserted, use seed value on port to determine where -- to start in the pseudo-random sequence if enable = '1' then if load = '1' then LFSR_Reg := parallel_in; else Feedback := LFSR_Reg(Width-1) xor NOR_All; -- look at old value; for N in Width-1 downto 1 loop if (Taps(N-1)='1') then XOR_Out(N-1) := LFSR_Reg(N-1) xor parallel_in(N) xor Feedback; else XOR_Out(N-1) := LFSR_Reg(N-1) xor parallel_in(N); end if; LFSR_Reg(N) := XOR_Out(N-1); end loop; OR_Chain(0) := XOR_Out(0) or XOR_Out(1); for N in 2 to Width-2 loop OR_Chain(N-1):= OR_Chain(N-2) or XOR_Out(N); end loop; NOR_All := not OR_Chain(Width-2); LFSR_Reg(0) := parallel_in(0) xor Feedback; end if; end if; end if; parallel_out <= LFSR_Reg; -- parallel data out serial_out <= LFSR_Reg(Width-1); -- serial data out end process; end RTL;