---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: -- Design Name: -- Module Name: REBEL - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- -- ===================================================================================== -- ===================================================================================== library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; -- A positive edge triggered FF made from 2 latches. Needed to do it this way so we -- can get to the output of the master for flush delay mode in REBEL. entity MuxScan_P_FF is Port ( D: in std_logic; SI : in std_logic; SE : in std_logic; Clk : in std_logic; RESET : in std_logic; ClkEn : in std_logic; QM : out std_logic; Q : out std_logic); end MuxScan_P_FF; -- Positive edge triggered FF. Latch a new value on the rising edge of clock and transfer -- to slave. architecture Behavioral of MuxScan_P_FF is signal Q1_reg, Q1_next: std_logic; signal Q2_reg, Q2_next: std_logic; signal Clk_not: std_logic; attribute RLOC: string; attribute RLOC of U0:label is "X0Y0"; attribute RLOC of U1:label is "X0Y1"; begin Clk_not <= not Clk; U0: LDCE generic map ( INIT => '0') -- Initial value of latch ('0' or '1') port map ( Q => Q1_reg, -- Data output CLR => RESET, -- Asynchronous clear/reset input D => Q1_next, -- Data input G => Clk_not, -- Gate input GE => ClkEn -- Gate enable input -- PRE => '0' -- Asynchronous preset/set input ); U1: LDCE generic map ( INIT => '0') -- Initial value of latch ('0' or '1') port map ( Q => Q2_reg, -- Data output CLR => RESET, -- Asynchronous clear/reset input D => Q2_next, -- Data input G => Clk, -- Gate input GE => ClkEn -- Gate enable input -- PRE => '0' -- Asynchronous preset/set input ); -- Connect the 2 latches to form a FF Q2_next <= Q1_reg; -- MUX-part of MUX scan of first latch (Q1/Q2) with SE select Q1_next <= D when '0', SI when others; QM <= Q1_reg; Q <= Q2_reg; end Behavioral; -- ===================================================================================== -- ===================================================================================== -- This is the local logic needed to integrate REBEL into the scan chain. Each -- MuxScanFF gets a copy of this logic. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; entity REBEL_MuxScanFFHoldLogic is Port ( QMPrev: in std_logic; SI: in std_logic; FD_L: in std_logic; SE: in std_logic; ModePrev: in std_logic; Q: in std_logic; SO: out std_logic; SE_L: out std_logic; ModeNext: out std_logic); end REBEL_MuxScanFFHoldLogic; architecture Behavioral of REBEL_MuxScanFFHoldLogic is signal Sel1, Sel2, SI_next, ModeNextNot: std_logic; begin -- This is the hold version of REBEL where the leftmost FFs in a mixed mode row hold the -- encoding for the path insertion. We need to preserve the contents of these FFs. This -- is accomplished by passing the Q output back into the scan path. Both SI and ModePrev -- MUST be '1' for preserve mode, otherwise send the SI through. Sel1 <= (SI and ModePrev); with Sel1 select SI_next <= SI when '0', Q when others; -- Select logic for the second select MUX with the SI and flush delay path (QMPrev) as input -- Force SI (output a 0) when SE (scan enable) is 1 or when ModePrev is 1 (storage FFs in mixed -- mode row are in scan config). Sel2 <= (SE nor ModePrev); -- MUX to select between QMPrev and SI with Sel2 select SO <= SI_next when '0', QMPrev when others; -- Propagating mode bit logic ModeNextNot <= ModePrev nand SI; ModeNext <= not ModeNextNot; -- Logic that controls the second MUX (one in MUXScanFF). Select D (output a 0) when in functional -- mode (FD_L is 1 in this case -- and is 0 for all other modes) or when you pattern match a -- 0 on SI and 1 on ModePrev (path insertion point). SE_L <= (ModePrev and ModeNextNot) nor FD_L; end Behavioral; -- ===================================================================================== -- ===================================================================================== -- This is a REBEL scan FF -- both control logic and modified DFF is provided here. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; entity REBEL_ScanFFHold is Port ( D: in std_logic; SI: in std_logic; SE: in std_logic; Clk_Capture: in std_logic; RESET: in std_logic; ClkEn_Capture: in std_logic; QMPrev: in std_logic; FD_L: in std_logic; ModePrev: in std_logic; QMNext: out std_logic; Q: out std_logic; ModeNext: out std_logic); end REBEL_ScanFFHold; architecture beh of REBEL_ScanFFHold is signal SE_L_int, Q_int: std_logic; signal SO_int: std_logic; begin -- The additional logic on the front of each FF needed to implement REBEL. This is the hold version REBELLogic: entity work.REBEL_MuxScanFFHoldLogic(Behavioral) port map (QMPrev=>QMPrev, SI=>SI, FD_L=>FD_L, SE=>SE, ModePrev=>ModePrev, SO=>SO_int, Q=>Q_int, SE_L=>SE_L_int, ModeNext=>ModeNext); -- The actual mux dff with an additional tap to allow access to the output of the master latch MuxScanFF: entity work.MuxScan_P_FF(Behavioral) port map (D=>D, SI=>SO_int, SE=>SE_L_int, Clk=>Clk_Capture, RESET=>RESET, ClkEn=>ClkEn_Capture, QM=>QMNext, Q=>Q_int); Q <= Q_int; end beh; -- ===================================================================================== -- ===================================================================================== -- This is the RCL (Row control logic) block library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; entity REBEL_MuxScanRowHeader_WL is Port ( Clk_Capture: in std_logic; SI: in std_logic; SE: in std_logic; FDMode: in std_logic; SORowHeader: out std_logic; FDRowHeader: out std_logic; ModeRowHeader: out std_logic); end REBEL_MuxScanRowHeader_WL; -- State 00X is functional mode and states 11X indicate a mixed mode of operation. -- State 010 defines flush delay mode. -- Mode | FF2 | FF1 | FF0 --============================ -- Func | 0 | 0 | X (000 can be functional, leaving 001 for something new). -- Scan | X | X | X -- FD | 0 | 1 | X (010 can be FD, leaving 011 for something new). -- Mixed | 1 | 1 | 0/1 architecture beh of REBEL_MuxScanRowHeader_WL is signal state_reg, state_next : std_logic_vector(2 downto 0); begin -- State registers in the row header. process(Clk_Capture) begin if ( Clk_Capture'event and Clk_Capture = '1' ) then state_reg <= state_next; end if; end process; -- Preserve contents of state registers unless we are in scan mode. If not, SI updates state_reg(2) while state_reg(2/1) updates -- state_reg(1/0) - right shift with SE select state_next <= state_reg when '0', SI & state_reg(2 downto 1) when others; -- Connect the right-most state element to the scan out pin of the header SORowHeader <= state_reg(0); -- FDHeader controls the select wire to the second MUX. It is set to 1 for functional mode (state 00X) only when FDMode is 1. Force -- functional mode if FDMode is 0 independent of the registers, but only if SE is 0 -- if SE is 1 -- force functional mode OFF. FDRowHeader <= ((state_reg(2) nor state_reg(1)) or not FDMode) and not SE; -- Set the mode bit to 1 when FDMode is in effect (1) and the row is set for mixed mode, -- but ignore the state registers and force it to 0 if SE is 1. ModeRowHeader <= (state_reg(2) and state_reg(1) and FDMode) and not SE; end beh; -- ===================================================================================== -- ===================================================================================== -- This module defines an entire REBEL row of length given by the input parameter. Needed to add hold mode -- to the leftmost FFs to preserve the contents. Also can use ATPG to accomplish this, by putting the '0' -- in the mixed-mode row one FF to the left of actual path you want to insert into the flush delay chain, -- so during the launch, the '0' moves one position to the right to the intended path insertion point. But -- this is more challenging. Going with the simplier approach -- for the FPGA experiments. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.Vcomponents.ALL; entity REBEL_MuxScanRow_WL is generic( NUM_SFFs: integer:= 272); Port ( D: in std_logic_vector(NUM_SFFs-1 downto 0); SI: in std_logic; SE: in std_logic; RESET: in std_logic; Clk_Capture: in std_logic; ClkEn_Capture: in std_logic; FDMode: in std_logic; QMPrevRow: in std_logic; QM : out std_logic_vector(NUM_SFFs-1 downto 0); Q: out std_logic_vector(NUM_SFFs-1 downto 0) ); end REBEL_MuxScanRow_WL; -- Basic operation of REBEL with MuxD scan is to launch an edge on the rising edge of Clk_Launch. A phase-shifted Clk_Capture -- is used here for the capture (REBEL) row. Key is to keep the ClkEn_Capture here high until the Clk_Capture event, and then -- deassert it immediately so we preserve the digital snapshot. architecture beh of REBEL_MuxScanRow_WL is constant MAX_COL_HEIGHT: integer := NUM_SFFs; signal ModeRowHeader : std_logic; signal FDRowHeader : std_logic; signal SORowHeader : std_logic; signal ModeNext : std_logic_vector(NUM_SFFs-1 downto 0); signal QL : std_logic_vector(NUM_SFFs-1 downto 0); signal QMNext : std_logic_vector(NUM_SFFs-1 downto 0); -- Had to take this out when the AES_3PipeStages was used because it can't fit the 272 FFs in a column on the V2Pro. Original version -- in REBEL_RLOC.vhd. Even with the multiple column modification below, we can meet timing when this is used. Not a big deal if we can -- not keep these together -- REBEL still works. -- attribute RLOC: string; -- attribute RLOC of REBEL_MuxRowHeader:label is "X0Y-4"; -- attribute RLOC of REBEL_ScanEle:label is "X0Y-2"; begin -- Row header for the entire row of ScanFFs. QMPrevRow connects either to the QMNext(0) of the previous row or to the SI pin if this is -- the first row (to allow calibration from SI pin) or '0'. REBEL_MuxRowHeader: entity work.REBEL_MuxScanRowHeader_WL(beh) port map (Clk_Capture=>Clk_Capture, SI=>SI, SE=>SE, FDMode=>FDMode, SORowHeader=>SORowHeader, FDRowHeader=>FDRowHeader, ModeRowHeader=>ModeRowHeader); -- First ScanFF has special connections REBEL_ScanEle: entity work.REBEL_ScanFFHold(beh) port map (D=>D(NUM_SFFs-1), SI=>SORowHeader, SE=>SE, Clk_Capture=>Clk_Capture, RESET=>RESET, ClkEn_Capture=>ClkEn_Capture, QMPrev=>QMPrevRow, FD_L=>FDRowHeader, ModePrev=>ModeRowHeader, QMNext=>QMNext(NUM_SFFs-1), Q=>QL(NUM_SFFs-1), ModeNext=>ModeNext(NUM_SFFs-1)); -- Instantiate the remaining ScanFFs. The last ModeNext does not connect to anything. Keep all of the elements of the REBEL row close in the -- layout if possible. GEN_SFF: for I in NUM_SFFs-2 downto 0 generate -- attribute RLOC of REBEL_ScanEle2:label is "X" & integer'image((2*(NUM_SFFs-2) - 2*I)/MAX_COL_HEIGHT*4) & "Y" & -- integer'image( ((2*(NUM_SFFs-2) - 2*I)*(((2*(NUM_SFFs-2) - 2*I)/MAX_COL_HEIGHT+1) REM 2) + (2*I + 2)*(((2*(NUM_SFFs-2) - 2*I)/MAX_COL_HEIGHT) REM 2)) REM MAX_COL_HEIGHT); begin REBEL_ScanEle2: entity work.REBEL_ScanFFHold(beh) port map (D=>D(I), SI=>QL(I+1), SE=>SE, Clk_Capture=>Clk_Capture, RESET=>RESET, ClkEn_Capture=>ClkEn_Capture, QMPrev=>QMNext(I+1), FD_L=>FDRowHeader, ModePrev=>ModeNext(I+1), QMNext=>QMNext(I), Q=>QL(I), ModeNext=>ModeNext(I)); end generate GEN_SFF; -- Connect ALL Q local outputs to the Q outputs. QM <= QMNext; Q <= QL; end beh;