Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: Math calculations in VHDL

  1. #1
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Math calculations in VHDL

    Hi all,
    I need a little help with my design, there are a few issues that I'm trying to resolve.
    My design flow is as following: A signal is sampled by a 16bit A2D, multiplied by 2 another 16bit signals (which results in 2 32bit signals). After a few manipulations I need to implement a formula that uses those 2 signals with division, multiplication and a few other functions that are calculated using LUTs. The LUTs are designed for a signal normalized to the range of 0 - pi/2. Note that after the formula the signals will be converted to 32bit floating-point signals.
    The formula requires some fractional calculations so I'm trying to use the fixed point package by David Bishop but I'm facing a few issues:
    1. How am I supposed to convert the 32bit signals (integer) to 32 fixed point numbers?
    2. I'm trying to divide the 2 32bit signals - what is the best way to do this? I tried the lpm_divide megafunction but I get a quotient and a remain while I need the whole number (i.e. 5.65 and not only 5).
    3. How exactly am I supposed to use the fixed-point package? I have the following libraries, is that enough?
    Library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use ieee.fixed_float_types.all;
    use ieee.fixed_pkg.all;

    Thanks in advance, help will be very appreciated.

  2. #2
    Join Date
    Jan 2012
    Posts
    31
    Rep Power
    1

    Default Re: Math calculations in VHDL

    Fixed point unlike the floating point arithmetics does not need any package at all. Every math operation implemented for integers is applicable to fixed point numbers.
    This might be helpful http://www.digitalsignallabs.com/fp.pdf
    As for the division this might be implemented using CORDIC algorithms.

  3. #3
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Re: Math calculations in VHDL

    I'm sorry if I wasn't clear enough, I understand the theory, my problem is with the implementation.
    First of all, how can I get the whole number from the lpm_divide function (including the fractional part).
    Second how can I scale the 32bit integers from the first part of my design so that they can be used as 32bit fixed-point fractions in the second part.

  4. #4
    Join Date
    Oct 2008
    Posts
    3,588
    Rep Power
    1

    Default Re: Math calculations in VHDL

    well, if its an integer, it has no fractional part to it. An integer is just a fixed point number with no fractional part. Unless you are talking about an integer you really meant was a fractional number and you biassed it by 2^n (where N is the number of fractional bits). In which case you need to tell us what the value of N is. You DONT need an LPM divide for this.

    Answer to questions
    1. You zero pad the inputs to the correct number of bits (integer and fractional) and the result will be correct.

    2. You need to just assign it to the correct sized ufixed or sfixed values (fixed point is just integers, offset by 2^n)

    either way, there are the to_ufixed and to_sfixed functions from the fixed point package.

    one point to note. You should not be using the std_logic_unsigned package, its not an IEEE standard. If you have a number, you shouldnt make it a std_logic_vector. There is no need to make ports std_logic_vector, they can be anything.

  5. #5
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Re: Math calculations in VHDL

    Hi Tricky, thank you for your reply.
    The reason I said that there are fractions is because when I divide the 2 32bit integers I will probably get a fraction.
    You mean that I should convert the 32bit integers to ufixed and then divide them and store the answer in a 64bit ufixed signal? I tried to do that but I got a strange error regarding the "/" operator, that's why I used the lpm_divide megafunction instead, which works for std_logic_vector.
    If I'm not using the std_logic_unsigned package I get an error even for a "+" sign, where am I wrong? Have I included all the correct files from the fixed-point package?

  6. #6
    Join Date
    Oct 2008
    Posts
    3,588
    Rep Power
    1

    Default Re: Math calculations in VHDL

    Yes, you will get a fraction. But if they start out as 32 bit, you will need a lot more bits to store the result. But making it a 32.32 sfixed is rather easy (remember integers are signed. For unsigned, you can only have a max of 31 bit integers). Do you really mean integers as in the VHDL type integer, or just a number that arrives via a 32 bit bus?

    signal my_number : sfixed(31 downto -32);
    my_number <= to_sfixed(input, 31, -32);

    And this is free in terms of synthesis because you're really just appending a load of zeros to it. Then you can convert this to a std_logic_vector (with the to_slv function) so you can connect it into the lpm divide. No, you should not use the "/" function unless you can get away with a pipeline length of 1 (until altera sort out their register placement inside infered dividers properly!)

    you shouldnt do + with std_logic_vectors, you should keep them in ufixed or sfixed type when you do this.

    I think at this point you need to post some code to show us what you're actually trying to do.

  7. #7
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Re: Math calculations in VHDL

    Below is a simple code that uses the lpm_divide megafunction to divide 2 32bit numbers. I tried to implement your comments from the previous post. The numbers are 32bit std_logic_vectors (I refered to them as integers i.e. a number that arrives via a 32bit bus). I want to get the full result (including the fractional part) because the next step will be performing modulus pi/2 on the result. I'm getting the following compilation error: Error (10344): VHDL expression error at PreNICOMFunction_fixed.vhd(: expression has 0 elements, but must have 64 elements (it refers to the line I_fp <= to_ufixed(I,31,-32)
    1. What am I doing wrong?
    2. How can I convert the divider result to a fractional number?

    Thanks again for your help.

    Library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.fixed_float_types.all;
    use ieee.fixed_pkg.all;

    entity PreNICOMFunction_fixed is
    port (
    clock : in std_logic;
    reset : in std_logic;
    I : in std_logic_vector (31 downto 0);
    Q : in std_logic_vector (31 downto 0);
    V0 : in std_logic_vector (31 downto 0) --;
    -- temp_res : out ufixed (31 downto -32)
    );
    end PreNICOMFunction_fixed;

    architecture rtl of PreNICOMFunction_fixed is

    component lpm_divider1 IS --32 clocks latency
    PORT (
    aclr : IN STD_LOGIC ;
    clock : IN STD_LOGIC ;
    denom : IN STD_LOGIC_VECTOR (63 DOWNTO 0);
    numer : IN STD_LOGIC_VECTOR (63 DOWNTO 0);
    quotient : OUT STD_LOGIC_VECTOR (63 DOWNTO 0);
    remain : OUT STD_LOGIC_VECTOR (63 DOWNTO 0)
    );
    END component lpm_divider1;

    type fsm_type1 is (s0, s1, s2, s3, s4);
    signal fsm1 : fsm_type1 := s0;
    signal QdivI : std_logic_vector (63 downto 0) := (others => '0');
    signal QdivI_remain : std_logic_vector (63 downto 0) := (others => '0');

    signal I_ff : std_logic_vector (31 downto 0) := (others => '0');
    signal Q_ff : std_logic_vector (31 downto 0) := (others => '0');
    signal I_fp : ufixed (31 downto -32) := (others => '0');
    signal Q_fp : ufixed (31 downto -32) := (others => '0');
    signal div_res : ufixed (31 downto -32) := (others => '0');
    signal cntr1 : ufixed (4 downto 0) := (others => '0');
    constant div_latency : ufixed (4 downto 0) := "11111";

    begin

    divider : component lpm_divider1
    port map (
    aclr => '0',
    clock => clock,
    denom => to_slv(I_fp),
    numer => to_slv(Q_fp),
    quotient => QdivI,
    remain => QdivI_remain
    );

    main : process (clock)
    begin
    if (rising_edge(clock)) then
    I_ff <= I;
    Q_ff <= Q;
    case fsm1 is
    when s0 => if ((I_ff /= I) or (Q_ff /= Q)) then --New data availabe
    I_fp <= to_ufixed(I,31,-32);
    Q_fp <= to_ufixed(Q,31,-32);
    fsm1 <= s1;
    end if;
    -- atanLUT_clk <= '0';

    when s1 => if (cntr1 < div_latency) then --Wait for the division operation to complete (Q/I)
    cntr1 <= cntr1 + 1;
    else
    cntr1 <= (others => '0');
    fsm1 <= s0;
    end if;

    when others => fsm1 <= s0;

    end case;
    end if;
    end process main;
    end rtl;

  8. #8
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Re: Math calculations in VHDL

    I modified the code so it compiles now but I still get a quotient and a remain and not the whole result. Besides, if my input is std_logic_vector why convert it to ufixed and then back to std_logic_vector?

    Library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.fixed_float_types.all;
    use ieee.fixed_pkg.all;

    entity PreNICOMFunction_fixed is
    port (
    clock : in std_logic;
    reset : in std_logic;
    I : in std_logic_vector (31 downto 0);
    Q : in std_logic_vector (31 downto 0);
    V0 : in std_logic_vector (31 downto 0) --;
    -- temp_res : out ufixed (31 downto -32)
    );
    end PreNICOMFunction_fixed;

    architecture rtl of PreNICOMFunction_fixed is

    component lpm_divider1 IS --32 clocks latency
    PORT (
    aclr : IN STD_LOGIC ;
    clock : IN STD_LOGIC ;
    denom : IN STD_LOGIC_VECTOR (63 DOWNTO 0);
    numer : IN STD_LOGIC_VECTOR (63 DOWNTO 0);
    quotient : OUT STD_LOGIC_VECTOR (63 DOWNTO 0);
    remain : OUT STD_LOGIC_VECTOR (63 DOWNTO 0)
    );
    END component lpm_divider1;

    type fsm_type1 is (s0, s1, s2, s3, s4);
    signal fsm1 : fsm_type1 := s0;
    signal QdivI : std_logic_vector (63 downto 0) := (others => '0');
    signal QdivI_remain : std_logic_vector (63 downto 0) := (others => '0');

    signal I_ff : std_logic_vector (31 downto 0) := (others => '0');
    signal Q_ff : std_logic_vector (31 downto 0) := (others => '0');
    signal I_fp : ufixed (31 downto -32) := (others => '0');
    signal Q_fp : ufixed (31 downto -32) := (others => '0');
    signal div_res : ufixed (31 downto -32) := (others => '0');
    signal cntr1 : ufixed (4 downto 0) := (others => '0');
    constant div_latency : ufixed (4 downto 0) := "11111";

    begin

    divider : component lpm_divider1
    port map (
    aclr => '0',
    clock => clock,
    denom => to_slv(I_fp),
    numer => to_slv(Q_fp),
    quotient => QdivI,
    remain => QdivI_remain
    );

    main : process (clock)
    begin
    if (rising_edge(clock)) then
    I_ff <= I;
    Q_ff <= Q;
    case fsm1 is
    when s0 => if ((I_ff /= I) or (Q_ff /= Q)) then --New data availabe
    I_fp <= to_ufixed(unsigned(I),31,-32);
    Q_fp <= to_ufixed(unsigned(Q),31,-32);
    fsm1 <= s1;
    end if;

    when s1 => if (cntr1 < div_latency) then --Wait for the division operation to complete (Q/I)
    cntr1 <= resize(cntr1 + 1, cntr1'high, cntr1'low);
    else
    cntr1 <= (others => '0');
    fsm1 <= s0;
    end if;

    when others => fsm1 <= s0;

    end case;



    end if;
    end process main;
    end rtl;

  9. #9
    Join Date
    Oct 2008
    Posts
    3,588
    Rep Power
    1

    Default Re: Math calculations in VHDL

    You will always get a remainder because you would otherwise need more bits to get and even smaller result in the quotient, which is not possible with lpm divide (64 bits being the max).

    You dont really need to use sfixed, but you still need to append all the '0's onto the end when connecting it to the lpm_divide.

    And I notice you dont have any outputs from this block - are you going to add them later?

  10. #10
    Join Date
    Feb 2011
    Posts
    60
    Rep Power
    1

    Default Re: Math calculations in VHDL

    Yes, the block is going to be more complicated. After the division I need to perform modulus pi/2 on the result and then use it with an LUT which is based on fractional numbers, that's why I need the fractional result. How can I find it?

Similar Threads

  1. VHDL Math Real & Quartus
    By James B in forum General Altera Discussion
    Replies: 11
    Last Post: June 6th, 2012, 10:28 PM
  2. complex math in VHDL
    By mohsen73 in forum General Altera Discussion
    Replies: 1
    Last Post: June 22nd, 2011, 05:23 AM
  3. how to link math.h
    By jay_1025 in forum Linux Forum
    Replies: 6
    Last Post: May 24th, 2006, 09:45 AM
  4. Did nios2 support math.h?
    By imported_markman in forum General Software Forum
    Replies: 2
    Last Post: February 24th, 2006, 05:23 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •