---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: -- Design Name: -- Module Name: LC_LFSRController - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- -- =================================================================================================== -- =================================================================================================== -- LFSR -- modeled after the version available in OpenCores. Preserves contents -- if set_seed and gen_bit are 0. If set_seed is 1, then load seed. If set_seed is -- 0 and gen_bit is 1, do a 1-bit shift library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_arith.all; use IEEE.STD_LOGIC_unsigned.all; entity LFSR32_wZERO is generic (LFSR_LEN_NB : integer := 32); port ( Clk: in std_logic; RESET: in std_logic; set_seed: in std_logic; gen_bit: in std_logic; seed: in std_logic_vector(LFSR_LEN_NB-1 downto 0); LFSR_out: out std_logic_vector(LFSR_LEN_NB-1 downto 0) ); end LFSR32_wZERO; architecture beh of LFSR32_wZERO is signal LFSR_reg, LFSR_next: std_logic_vector(LFSR_LEN_NB-1 downto 0); signal next_bit: std_logic; signal nor_bit: std_logic; signal request: std_logic_vector(1 downto 0); begin -- state and register logic process(Clk, RESET) begin if (RESET = '1') then LFSR_reg <= (LFSR_LEN_NB-1 downto 1=>'0') & (0=>'1'); elsif (Clk'event and Clk = '1') then LFSR_reg <= LFSR_next; end if; end process; -- Set seed takes priority if both are set request <= set_seed & gen_bit; -- Add the 'all zero' state, which requires a bitwise nor of the lower 31 bits. nor_bit <= not(LFSR_reg(31) or LFSR_reg(30) or LFSR_reg(29) or LFSR_reg(28) or LFSR_reg(27) or LFSR_reg(26) or LFSR_reg(25) or LFSR_reg(24) or LFSR_reg(23) or LFSR_reg(22) or LFSR_reg(21) or LFSR_reg(20) or LFSR_reg(19) or LFSR_reg(18) or LFSR_reg(17) or LFSR_reg(16) or LFSR_reg(15) or LFSR_reg(14) or LFSR_reg(13) or LFSR_reg(12) or LFSR_reg(11) or LFSR_reg(10) or LFSR_reg(9) or LFSR_reg(8) or LFSR_reg(7) or LFSR_reg(6) or LFSR_reg(5) or LFSR_reg(4) or LFSR_reg(3) or LFSR_reg(2) or LFSR_reg(1) or LFSR_reg(0)); -- The (primitive) polynomial: OLD right-shift version. -- next_bit <= LFSR_reg(31) xor LFSR_reg(21) xor LFSR_reg(1) xor LFSR_reg(0); -- New version (see ../../README.jim for table for left-shift version) next_bit <= LFSR_reg(31) xor LFSR_reg(6) xor LFSR_reg(5) xor LFSR_reg(1); -- Preserve contents or put the seed in or shift the LSFR to generate the new bit LFSR_next <= LFSR_reg when (request = "00") else seed when (request(1) = '1') else LFSR_reg(LFSR_LEN_NB-2 downto 0) & next_bit; LFSR_out <= LFSR_reg; end beh; -- =================================================================================================== -- =================================================================================================== library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; -- This module controls the random values scanned into the launch registers. It has 3 modes. When init_seed is 1, -- the input register value is placed into the seed_hold_reg. If init_seed is low and next_seq is 1, then the -- current value OUTPUT value of the LFSR is loaded into seed_hold_reg (and becomes the start value). If both -- signals are low, then the seed_hold_reg is preserved. When 'start' is asserted, the value in the seed_hold_reg -- is loaded into the LFSR. The LFSR is then clocked for n cycles to load the scan chain with a random sequence -- with 'ScanEn' set high. NOTE: the first two modes do NOT need to have 'start' asserted. This is a change from -- the V2Pro experiments. I was carring out the 'seed' operation AND loading the sequence in LCTest and then AGAIN -- loading the sequence in LCSweep, so the load in LCTest was not necessary. entity LC_LFSRController is Generic( LFSR_LEN_LB: integer := 5; LFSR_LEN_NB: integer := 32; LFSR_SCAN_CYCLES_LB: integer := 9; LFSR_SCAN_CYCLES_NB: integer := 512); port( Clk: in std_logic; RESET: in std_logic; start: in std_logic; init_seed: in std_logic; next_seq: in std_logic; seed_in: in std_logic_vector(LFSR_LEN_NB-1 downto 0); ready: out std_logic; ScanEn: out std_logic; scan_bit: out std_logic); end LC_LFSRController; ARCHITECTURE beh of LC_LFSRController is type state_type is (idle, load_LFSR, load_scan_chain, completed); signal state_reg, state_next: state_type; signal ready_reg, ready_next: std_logic; signal seed_hold_reg, seed_hold_next: std_logic_vector(LFSR_LEN_NB-1 downto 0); signal LFSR_out: std_logic_vector(LFSR_LEN_NB-1 downto 0); signal cnt_reg, cnt_next: unsigned(LFSR_SCAN_CYCLES_LB-1 downto 0); signal set_seed: std_logic; signal gen_bit: std_logic; begin -- LFSR primitive, n bit polynomial LFSR32: entity work.LFSR32_wZERO(beh) generic map(LFSR_LEN_NB=>LFSR_LEN_NB) port map (Clk=>Clk, RESET=>RESET, set_seed=>set_seed, gen_bit=>gen_bit, seed=>seed_hold_reg, LFSR_out=>LFSR_out); -- State and register logic process(Clk, RESET) begin if (RESET = '1') then state_reg <= idle; seed_hold_reg <= (0=>'1') & (1 to LFSR_LEN_NB-1=>'0'); cnt_reg <= (others=>'0'); ready_reg <= '1'; elsif (Clk'event and Clk = '1') then state_reg <= state_next; seed_hold_reg <= seed_hold_next; cnt_reg <= cnt_next; ready_reg <= ready_next; end if; end process; -- Combo logic for state machine, iteration cnter and shift operations in data path process (state_reg, seed_hold_reg, cnt_reg, init_seed, next_seq, start, seed_in, LFSR_out, ready_reg) begin state_next <= state_reg; ready_next <= ready_reg; set_seed <= '0'; seed_hold_next <= seed_hold_reg; cnt_next <= cnt_reg; ScanEn <= '0'; gen_bit <= '0'; case state_reg is when idle => ready_next <= '1'; -- Load up the initial seed, or use the output of the LFSR as the next seed when requested. -- Note this is a separate operation now (does NOT require 'start' to be asserted) -- see -- note above. if ( init_seed = '1' ) then seed_hold_next <= seed_in; elsif ( next_seq = '1' ) then seed_hold_next <= LFSR_out; end if; -- Start a scan operation if ( start = '1' ) then ready_next <= '0'; -- Reset the counter cnt_next <= (others=>'0'); state_next <= load_LFSR; end if; -- Transfer the seed in seed_hold_reg to the LFSR. when load_LFSR => set_seed <= '1'; state_next <= load_scan_chain; -- Start loading the scan chain when load_scan_chain => -- Control scan enable to 1 and keep it there until the scan operation completes ScanEn <= '1'; -- Also enable the LFSR to generate the next bit. gen_bit <= '1'; -- Count up to the length cnt_next <= cnt_reg + 1; -- Exit and indicate completion one LFSR scan cycles have been carried out if ( cnt_reg = LFSR_SCAN_CYCLES_NB - 1 ) then state_next <= completed; end if; when completed => ready_next <= '1'; state_next <= idle; end case; end process; -- Set the scan in bit to the right-most bit of the LFSR scan_bit <= LFSR_out(0); ready <= ready_reg; end beh;