Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20707 Discussions

Code Optimization for FPGA

Altera_Forum
Honored Contributor II
1,020 Views

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;
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
306 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

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)
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

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)
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

 

--- 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"?
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
306 Views

Thank you!

0 Kudos
Reply