![]()
작성일: 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:
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));
Cautions:
- This is a VHDL solution. A Verilog solution is more complex.
- We developed this package with Synplicity. It may work with other synthesizers, or it may not.
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) ![]()
![]()
Send to a colleague |
Print this document