-- VirtexLut.vhd - Force logic to a single LUT for the Xilinx Virtex family -- -- Copyright (c) 2001 RockyLogic Inc. -- ----------------------------------------------------------------------------- -- Log -- -- revision 1.0 12-Jun-01 te -- Initial implementation ----------------------------------------------------------------------------- -- -- Typical usage: -- -- signal a,b,c,d,x : std_logic; -- -- LU: VLut4 generic map ( ExprStr => "((I0*I1)@(I2*~I3))" ) -- port map (I0=>a, I1=>b, I2=>c, I3=>d, O=>x ); -- -- This evaluates the following expression: -- -- x <= (a and b) xor ( c and (not d)); -- ----------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; --synthesis translate_off use std.textio.all; library unisim; use unisim.vcomponents.all; --synthesis translate_on package LUT_XCV is -- generic attribute attribute xc_map : string; ----------------------------------------------------------------------------- -- declare our implementations of LUT2/LUT3/LUT4 ----------------------------------------------------------------------------- component VLut2 is generic( ExprString : string := "(I0*I1)"); port ( I0,I1 : in std_logic; O : out std_logic ); end component; ----------------------------------------------------------------------------- component VLut3 is generic( ExprString : string := "(I0*I1*I2)"); port ( I0,I1,I2 : in std_logic; O : out std_logic ); end component; ----------------------------------------------------------------------------- component VLut4 is generic( ExprString : string := "(I0*I1*I2*I3)"); port ( I0,I1,I2,I3 : in std_logic; O : out std_logic ); end component; ----------------------------------------------------------------------------- -- see the package body for this function function VExprEval( s : string; DEBUG : boolean := false) return bit_vector; end package LUT_XCV; -- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- package body LUT_XCV is -- calculate the 16-bit INIT string corresponding to an arbitrary -- function of I0..I3. -- the operators are -- op priority (0=lowest) -- ( 0 left paren -- + 1 OR -- *,@ 2 AND,XOR -- ~ 3 NOT -- Ix 4 one of the I0..I3 variables -- -- the method is to -- convert the infix expression to a postfix (reverse polish) string -- evaluate the RP for all 16 possible sets of Ix -- function VExprEval( s : string; DEBUG : boolean := false) return bit_vector is variable r: bit_vector(0 to 15); variable iInputStr: integer; variable I0,I1,I2,I3: boolean; type TRps is array (0 to 100) of character; variable Rps : TRps; -- reverse polish (RP) string variable RpsLen : integer; type TPri is array (0 to 15) of integer; type TStk is array (0 to 15) of character; variable Pri : TPri; variable Stk : TStk; variable StkLen : integer; variable Priority: integer; type TEStack is array (0 to 15) of boolean; variable EStack : TEStack; variable ELen : integer; variable EResult : boolean; variable iRps : integer; variable ch : character; variable Obuff : string (1 to 80); --synthesis translate_off variable Lout : line; --synthesis translate_on begin --synthesis translate_off if DEBUG then write(Lout, "Input string : "); write(Lout, s); writeline(OUTPUT, Lout); end if; --synthesis translate_on -- first build the Reverse Polish sequence RpsLen := 0; iInputStr := 1; StkLen := 0; SCAN_LOOP: for iInputStr in s'low to s'high loop -- crude GetToken() routine ch := s(iInputStr); next SCAN_LOOP when ch=' '; -- skip spaces next SCAN_LOOP when ch='I'; -- I0/I1/I2/I3 -- prioritise token case ch is when '(' => Priority := 0; when '+' => Priority := 1; when '*'|'@' => Priority := 2; when '~' => Priority := 3; when '0'|'1'|'2'|'3' => Priority := 4; when others => Priority := 99; end case; -- evaluate token case ch is when '(' => Stk(StkLen) := ch; Pri(StkLen) := Priority; StkLen := StkLen+1; when '+'|'*'|'@'|'~' => while (StkLen /= 0) and (Priority <= Pri(StkLen-1)) loop StkLen := StkLen-1; -- pop TOS to RP string Rps(RpsLen) := Stk(StkLen); RpsLen := RpsLen+1; end loop; Stk(StkLen) := ch; -- then push this operator Pri(StkLen) := Priority; StkLen := StkLen+1; when '0'|'1'|'2'|'3' => -- variable Rps(RpsLen) := ch; RpsLen := RpsLen+1; when ')' => RBLOOP: loop if StkLen=0 then -- unexpected all done report "Unexpected unmatched ')' in input string."; exit RBLOOP; elsif Stk(StkLen-1)='(' then -- pop and discard StkLen := StkLen-1; exit RBLOOP; else StkLen := StkLen-1; -- pop TOS to RP string Rps(RpsLen) := Stk(StkLen); RpsLen := RpsLen+1; end if; end loop; when others => report "Unexpected token in source string: " & ch; end case; end loop; if StkLen /= 0 then report "Unexpected end of input string. Unparsed characters remain."; end if; Rps(RpsLen) := '.'; -- add an 'end' flag RpsLen := RpsLen+1; --synthesis translate_off if DEBUG then write(Lout, "RP string is : "); for iRps in 0 to RpsLen-1 loop Obuff(iRps+1) := Rps(iRps); end loop; write(Lout, Obuff(1 to RpsLen)); writeline(OUTPUT, Lout); end if; --synthesis translate_on -- evaluate the reverse polish for 0..15 for i in 0 to 15 loop I0 := ((i ) rem 2)=1; I1 := ((i/2) rem 2)=1; I2 := ((i/4) rem 2)=1; I3 := ((i/8) rem 2)=1; ELen := 0; iRps := 0; EX_LOOP: loop ch := Rps(iRps); iRps := iRps+1; case ch is when '~' => EStack(ELen-1) := not EStack(ELen-1); when '+' => EStack(ELen-2) := EStack(ELen-1) or EStack(ELen-2); ELen := ELen-1; when '*' => EStack(ELen-2) := EStack(ELen-1) and EStack(ELen-2); ELen := ELen-1; when '@' => EStack(ELen-2) := EStack(ELen-1) xor EStack(ELen-2); ELen := ELen-1; when '0' => EStack(ELen) := I0; ELen := ELen+1; when '1' => EStack(ELen) := I1; ELen := ELen+1; when '2' => EStack(ELen) := I2; ELen := ELen+1; when '3' => EStack(ELen) := I3; ELen := ELen+1; when '.' => -- all done EResult := EStack(ELen-1); exit EX_LOOP; when others => report "Unexpected token in RP string: " & ch; end case; end loop; if EResult then r(i) := '1'; else r(i) := '0'; end if; end loop; --synthesis translate_off if DEBUG then write(Lout,"INIT(15..0) is : "); for i in 0 to 15 loop if r(i)='1' then Obuff(16-i) := '1'; else Obuff(16-i) := '0'; end if; end loop; write(Lout, Obuff(1 to 16)); writeline(OUTPUT, Lout); end if; --synthesis translate_on return r; end VExprEval; end package body LUT_XCV; ------------------------------------------------------------------------ -- define the 'VLut4' component library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.LUT_XCV.all; entity VLut4 is generic(ExprString : string := "(I0*I1*I2*I3)" ); port (I0,I1,I2,I3 : in std_logic := '0'; O : out std_logic); end VLut4; architecture struct of VLut4 is attribute xc_map of struct : architecture is "lut"; constant LutBits : bit_vector(0 to 15) := VExprEval(ExprString); signal AddrBits : std_logic_vector(3 downto 0); signal Addr : integer range 0 to 15; begin AddrBits <= (I3, I2, I1, I0); Addr <= to_integer( AddrBits ); O <= to_stdulogic(LutBits(Addr)); end struct; ------------------------------------------------------------------------ -- define the 'VLut3' component library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.LUT_XCV.all; entity VLut3 is generic(ExprString : string := "(I0*I1*I2)" ); port (I0,I1,I2 : in std_logic := '0'; O : out std_logic); end VLut3; architecture struct of VLut3 is attribute xc_map of struct : architecture is "lut"; constant LutBits : bit_vector(0 to 15) := VExprEval(ExprString); signal AddrBits : std_logic_vector(2 downto 0); signal Addr : integer range 0 to 7; begin AddrBits <= (I2, I1, I0); Addr <= to_integer( AddrBits ); O <= to_stdulogic(LutBits(Addr)); end struct; ------------------------------------------------------------------------ -- define the 'VLut2' component library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.LUT_XCV.all; entity VLut2 is generic(ExprString : string := "(I0*I1)" ); port (I0,I1 : in std_logic := '0'; O : out std_logic); end VLut2; architecture struct of VLut2 is attribute xc_map of struct : architecture is "lut"; constant LutBits : bit_vector(0 to 15) := VExprEval(ExprString); signal AddrBits : std_logic_vector(1 downto 0); signal Addr : integer range 0 to 3; begin AddrBits <= ( I1, I0); Addr <= to_integer( AddrBits ); O <= to_stdulogic(LutBits(Addr)); end struct; ------------------------------------------------------------------------ -- EOF VirtexLut.vhd