작성일: 2003.01.26

Locking Logic to a Single Xilinx Virtex LUT...

* How do you constrain HDL logic so that it is mapped to a single LUT in a Xilinx Virtex or Virtex-E part? This package lets you define your VHDL logic like this:

* This evaluates the following expression:

* Cautions:

* A very nice VHDL function that parses and converts a boolean expression to a bit vector that can be used for INIT values on XIlinx LUT primitives


-- 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
출처: http://www.rockylogic.com/freebies.html

* 파일명: VIRTEXLUT.VHD (11,242 bytes) * download *

** - siMPLY BETTER iNFORMATIONs - **

** Send mail ** Send to a colleague | ** Print icon ** Print this document