Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

Code Optimization for FPGA

I was told the multiplier "*" in the code blow will dramatically slow down the operating speed(Fmax) of FPGA. But i don't konw why. Could somebody give me some hints on it? Any idea to optimize it?

-- Color bar(V) (White,Yellow,Cyan,Green,Magenta,Red,Blue,Black)p_main: process(Clk)
begin
	if rising_edge(Clk) then      	
        HelperColorBars <= "000"; -- black	
      	if unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),3) then
      		HelperColorBars <= "111"; -- white
      	elsif unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),2) then
      		HelperColorBars <= "011"; -- yellow
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*3) then
      		HelperColorBars <= "110"; --Cyan
      	elsif unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),1) then
      		HelperColorBars <= "010"; --Green
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*5) then
      		HelperColorBars <= "101"; --Magenta
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*6) then
      		HelperColorBars <= "001"; --red
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*7) then
      		HelperColorBars <= "100"; --blue
      	end if;
end process; 

See below for the complete code.

library ieee;use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.log2;
use ieee.math_real.ceil;
entity IPG1_FIP_worker_testpattern is
        generic(
            Intended_device_family         : string := "Default";
            Intended_compiler              : string := "Default";
            BurstLength                    : integer := 64;
            IPG1_Max_combine_nr            : integer := 8
        );
        port (
            -- General
            Clk     : in std_logic;
            Reset   : in std_logic;
			
			-- Instruction interface
			Setting_TotPixel  : in std_logic_vector(15 downto 0) := (others => '0');  -- T -1
			Setting_TotLine   : in std_logic_vector(15 downto 0) := (others => '0');  -- T -1
			Setting_Pixel     : in std_logic_vector(15 downto 0) := (others => '0');  -- T -1
			Setting_Line      : in std_logic_vector(15 downto 0) := (others => '0');  -- T -1
			Setting_Field     : in std_logic_vector( 3 downto 0) := (others => '0');  -- T -1
			Setting_R         : in std_logic_vector(11 downto 0) := (others => '0');  -- T -1
			Setting_G         : in std_logic_vector(11 downto 0) := (others => '0');  -- T -1
			Setting_B         : in std_logic_vector(11 downto 0) := (others => '0');  -- T -1
			Setting_Pattern   : in std_logic_vector( 3 downto 0) := (others => '0');  -- T -1
			Setting_Disables  : in std_logic_vector( 2 downto 0) := (others => '0');  -- T  0
			
            -- Input
			In_Start                    : in  std_logic := '0';   -- T  0
			In_DE                       : in  std_logic := '0';   -- T  0
			In_Data                     : in  std_logic_vector(35 downto 0) := (others => '0');  -- T  0
        
			-- Output
			Out_Start                   : out std_logic := '0';   -- T  1
			Out_DE                      : out std_logic := '0';   -- T  1
			Out_Data                    : out std_logic_vector(35 downto 0) := (others => '0')  -- T  1				
            );
end IPG1_FIP_worker_testpattern;
architecture RTL of IPG1_FIP_worker_testpattern is
-- Defined test patterns
constant c_NoPattern   : integer := 0;
constant c_Geometry    : integer := 1;
constant c_Colorbars   : integer := 2;
constant c_Graybars    : integer := 3;
constant c_GrayRamp    : integer := 4;
constant c_Purity      : integer := 5;
-- Define helpers
constant c_Outline       : integer := 0;  -- Is pixel on outline
constant c_Centerline    : integer := 1;  -- Is pixel on centerline
constant c_Hatch32       : integer := 2;  -- Is pixel on 32 hatch
constant c_Hatch32Moving : integer := 3;  -- Is pixel on moving 32 hatch
constant c_NrOfHelpers   : integer := 4;  -- Total amount of helpers
-- Helpers
signal Helper            : std_logic_vector(c_NrOfHelpers-1 downto 0) := (others => '0');
signal HelperColorBars   : unsigned(2 downto 0) := (others => '0');
-- Software defined color
signal Color   : std_logic_vector(35 downto 0) := (others => '0');
-- Half intensity  content
signal Data2   : std_logic_vector(35 downto 0) := (others => '0');
-- Half intensity  Software defined color
signal Color2  : std_logic_vector(35 downto 0) := (others => '0');
-- Gray color  value 64 (on 256 scale)
signal Gray64  : std_logic_vector(35 downto 0) := (10 => '1', 22 => '1', 34 => '1', others => '0');
		
begin
-- Color delivered by settings
Color  <= Setting_B & Setting_G & Setting_R;
-- Half intensity
Data2  <= '0' &   In_Data(35 downto 25) & '0' &   In_Data(23 downto 13) & '0' &   In_Data(11 downto 1);
Color2 <= '0' & Setting_B(11 downto  1) & '0' & Setting_G(11 downto  1) & '0' & Setting_R(11 downto 1);
p_main: process(Clk)
begin
	if rising_edge(Clk) then
		-- Time -1 ----------------------------------------------------------------------------------------------------------
		
		-- Helpers default
		Helper <= (others => '0');
		
		-- Outline
		if Setting_Pixel = 0 or Setting_Pixel = Setting_TotPixel or Setting_Line  = 0 or Setting_Line  = Setting_TotLine  then
			Helper(c_Outline) <= '1'; 
		end if;
		
		-- Center line
		if unsigned(Setting_Pixel) = shift_right(unsigned(Setting_TotPixel),1) or unsigned(Setting_Line) = shift_right(unsigned(Setting_TotLine),1) then
			Helper(c_Centerline) <= '1';
		end if;
		
		-- Hatch 32x32
		if  Setting_Pixel(4 downto 0) = "00000" or Setting_Line(4 downto 0) = "00000"  then
			Helper(c_Hatch32) <= '1'; 
		end if;
		-- Hatch 32x32 Moving
		if  Setting_Pixel(4 downto 0) = Setting_Field & '0' or Setting_Line(4 downto 0) = Setting_Field & '0' then
			Helper(c_Hatch32Moving) <= '1';
		end if;
		
		-- Color bar(V) (White,Yellow,Cyan,Green,Magenta,Red,Blue,Black)
      	HelperColorBars <= "000"; -- black	
      	if unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),3) then
      		HelperColorBars <= "111"; -- white
      	elsif unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),2) then
      		HelperColorBars <= "011"; -- yellow
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*3) then
      		HelperColorBars <= "110"; --Cyan
      	elsif unsigned(Setting_Pixel) < shift_right(unsigned(Setting_TotPixel),1) then
      		HelperColorBars <= "010"; --Green
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*5) then
      		HelperColorBars <= "101"; --Magenta
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*6) then
      		HelperColorBars <= "001"; --red
      	elsif unsigned(Setting_Pixel) < ((shift_right(unsigned(Setting_TotPixel),3))*7) then
      		HelperColorBars <= "100"; --blue
      	end if; 
				
		-- Time 0 ----------------------------------------------------------------------------------------------------------
		
		-- default value
		Out_Data  <= In_Data; 
		
		case to_integer(unsigned(Setting_Pattern)) is
		
			when c_Geometry =>
				Out_Data <= Gray64;				
				if Helper(c_Hatch32) = '1' then
					Out_Data <= Color2;
				end if;
				if Helper(c_Outline) = '1' or Helper(c_Centerline) = '1' then
					Out_Data <= Color;
				end if;
				
			when c_Purity =>
				Out_Data <= Color;
				
			when c_Colorbars =>
			    Out_Data <= (others => '0');
				for i in 0 to 2 loop
					if HelperColorBars(i) = '1' then
						Out_Data(11+i*12 downto i*12) <= (others => '1');
					end if;
		        end loop;
			
			--	when  =>
			
			when c_NoPattern =>
			when others => 
				Out_Data  <= In_Data; 
				
		end case;
		
		-- Disable a color
		for i in 0 to 2 loop
			if Setting_Disables(i) = '1' then
				Out_Data(11+i*12 downto i*12) <= (others => '0');
			end if;
		end loop;
		
		-- Delay the control signals 
		Out_Start <= In_Start;
		Out_DE    <= In_DE;
			
		-- Reset ------------------------------------------------------------------------------------------------------------		
		if Reset = '1' then
			-- Only reset control stuff that is realy needed  not the data path!
		end if;
	end if;
end process;
    
end RTL;

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    My understanding is that the compiler inserts a multiplier for each inference occurrence in a construct.

    you can keep the construct but remove mult inference, use one mult and use the constrcut as switch for multiplier input
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Because you're expecting a non trivial multiply (ie non power of 2 which is simply a bit shift) and a compare to be done in a single clock cycle. Longer logic chains = slower clock speed. This is on top of the priority encode you build with all of those elseifs.

    You'd be much better off trying to pipeline it all somehow (not much I can say, as you are using inputs directly).

    On a side note - why are all your setting_* signals std_logic_vectors? why not just make them unsigned in the port map, and you'll save yourself a load of RSI.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    alternatively, to multiply x by 2,3,4,5,6,7

    use adders or shift

    2*x (shift as you done it);

    3*x (add above to x)

    4*x (shift)

    5*x(add 2*x to 3*x)

    6*x(add 3*x,3*x)

    7*x (add x to 6*x)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That is just an open coded multiply, to multiply x by y (y 0..7):

    (y & 1 ? x : 0) + (y & 2 ? 2 * x : 0) + (y & 4 ? 4 * x : 0)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Because you're expecting a non trivial multiply (ie non power of 2 which is simply a bit shift) and a compare to be done in a single clock cycle. Longer logic chains = slower clock speed. This is on top of the priority encode you build with all of those elseifs.

    You'd be much better off trying to pipeline it all somehow (not much I can say, as you are using inputs directly).

    On a side note - why are all your setting_* signals std_logic_vectors? why not just make them unsigned in the port map, and you'll save yourself a load of RSI.

    --- Quote End ---

    What is RSI? Could explain more on the diffence of using "std_logic_vector" and "unsinged"?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Rsi = repetative strain injury

    The std_ logic_vector type is meant to represent a collection of bits, while the unsigned type represents an unsigned integer. The numeric_std library defines functions for arithmatic with unsigned and signed types. There are no standard libraries for arithmatic with std_logic_vector, because it is not meant to represent anything.