Forum Discussion

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

Polynomial Evaluation

Hello,

I'm totally new to VHDL and i'm trying to do a polynonamial evaluation. In particular I have a signed 16 bit value (x) and I want to obtain y=d*x^3+c*x^2+b*x+a.

I have created a signed multiplier:

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.numeric_std.all;

ENTITY my_signed_multiplier IS

PORT( in1, in2 : IN signed (15 DOWNTO 0);

clk,clr : IN std_logic;

result : OUT signed(15 DOWNTO 0));

END ENTITY my_signed_multiplier;

ARCHITECTURE logic OF my_signed_multiplier IS

SIGNAL in1_reg, in2_reg : signed (15 DOWNTO 0);

SIGNAL out_reg : signed (31 DOWNTO 0);

BEGIN

PROCESS(clk,clr)

BEGIN

IF clr ='1' THEN

in1_reg<=(OTHERS => '0');

in2_reg<=(OTHERS => '0');

out_reg<=(OTHERS => '0');

ELSIF rising_edge(clk) THEN

in1_reg<=in1;

in2_reg<=in2;

out_reg<=in1_reg*in2_reg;

END IF;

END PROCESS;

result<=out_reg(31 DOWNTO 16);

END ARCHITECTURE logic;

Now I was supposed to create another entity which has a generic variable (eg: pow : integer ) that specifies how many instance of my_signed multiplier use to obtain the correct signal power elevation. By the way now I'm stuck is I don't know exactly how to do it.

Any suggestions is appreciated . Thank you !

25 Replies

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

    --- Quote Start ---

    Hello guys,

    I've modified my vhdl code as you suggested. Hope it works and that all is finally ok !

    LIBRARY ieee;
    USE ieee.std_logic_1164.all;
    USE ieee.numeric_std.all;
    ENTITY my_poly_test IS
        PORT( in1 : IN SIGNED (15 DOWNTO 0);
                    clk,clr : IN std_logic;
                 result : OUT SIGNED (15 DOWNTO 0));
    END ENTITY my_poly_test;
    ARCHITECTURE logic OF my_poly_test IS
        SIGNAL x2 : SIGNED (15 DOWNTO 0);
        SIGNAL x3 : SIGNED (15 DOWNTO 0);
        SIGNAL x4 : SIGNED (15 DOWNTO 0);
        SIGNAL x5 : SIGNED (15 DOWNTO 0);
        SIGNAL x6 : SIGNED (15 DOWNTO 0);
        SIGNAL x7 : SIGNED (15 DOWNTO 0);
        SIGNAL in1_1d : STD_LOGIC_VECTOR(15 DOWNTO 0);
        SIGNAL in1_2d : STD_LOGIC_VECTOR(15 DOWNTO 0);
        SIGNAL in1_3d  : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL in1_4d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL in1_5d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL x_6d : STD_LOGIC_VECTOR(15 DOWNTO 0);
        SIGNAL x2_5d : STD_LOGIC_VECTOR(15 DOWNTO 0);
        SIGNAL x3_4d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL x4_3d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL x5_2d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL x6_1d : STD_LOGIC_VECTOR (15 DOWNTO 0);
        SIGNAL x7_d : STD_LOGIC_VECTOR(15 DOWNTO 0);
        SIGNAL sum : SIGNED(31 DOWNTO 0);
        
                  
        BEGIN
            M1 :   work.my_signed_multiplier PORT MAP (in1=>in1,in2=>in1,clk=>clk,clr=>clr,result=>x2);
            
            DFF1:  work.my_generic_dff_aclr GENERIC MAP(delay =>1) PORT MAP (d => std_logic_vector(in1), clk => clk, clr=> clr, q => in1_1d);
           M2 :   work.my_signed_multiplier PORT MAP (in1=> signed(in1_1d),in2=> x2,clk=>clk,clr=>clr,result => x3);
            
            DFF2:  work.my_generic_dff_aclr GENERIC MAP(delay =>1) PORT MAP (d => in1_1d,clk => clk,clr=> clr,q =>in1_2d);
            M3 :   work.my_signed_multiplier PORT MAP (in1=> signed(in1_2d),in2=>x3,clk=>clk,clr=>clr,result => x4);
            
            DFF3:  work.my_generic_dff_aclr GENERIC MAP(delay =>1) PORT MAP (d =>in1_2d,clk => clk,clr=> clr,q =>in1_3d);
            M4 :   work.my_signed_multiplier PORT MAP (in1=> signed(in1_3d),in2=>x4,clk=>clk,clr=>clr,result => x5);
            
            DFF4:  work.my_generic_dff_aclr GENERIC MAP(delay =>1) PORT MAP (d => in1_3d,clk =>clk,clr=> clr,q =>in1_4d);
            M5 :   work.my_signed_multiplier PORT MAP (in1=> signed(in1_4d),in2=>x5,clk=>clk,clr=>clr,result => x6);
            
            DFF5:  work.my_generic_dff_aclr GENERIC MAP(delay =>1) PORT MAP (d => in1_4d,clk =>clk,clr=> clr,q =>in1_5d);
            M6 :   work.my_signed_multiplier PORT MAP (in1=> signed(in1_5d),in2=>x6,clk=>clk,clr=>clr,result => x7);
            
            DFF6:  work.my_generic_dff_aclr  GENERIC MAP(delay =>1) PORT MAP (d => std_logic_vector(x6), clk => clk, clr=> clr, q =>x6_1d);
            DFF7:  work.my_generic_dff_aclr  GENERIC MAP(delay =>2) PORT MAP (d => std_logic_vector(x5), clk => clk, clr=> clr, q =>x5_2d);
            DFF8:  work.my_generic_dff_aclr  GENERIC MAP(delay =>3) PORT MAP (d => std_logic_vector(x4), clk => clk, clr=> clr, q =>x4_3d);
            DFF9:  work.my_generic_dff_aclr  GENERIC MAP(delay =>4) PORT MAP (d => std_logic_vector(x3), clk => clk, clr=> clr, q =>x3_4d);
            DFF10: work.my_generic_dff_aclr GENERIC MAP(delay =>5) PORT MAP (d => std_logic_vector(x2), clk => clk, clr=> clr, q =>x2_5d);
            DFF11: work.my_generic_dff_aclr GENERIC MAP(delay =>6) PORT MAP (d => std_logic_vector(in1), clk => clk, clr=> clr,q =>x_6d);
        PROCESS(clk,clr)
        BEGIN
            IF clr ='1' THEN
            result<=(OTHERS => '0');
            
            ELSIF rising_edge(clk) THEN
                sum<=1+signed(("0000000000000000")&x_6d)+signed(x2_5d&("0000000000000000"))+signed(x3_4d&("0000000000000000"))+signed(x4_3d&("0000000000000000"))+signed(x5_2d&("0000000000000000"))+signed(x6_1d&("0000000000000000"))+signed(x7_d&("0000000000000000"));
                result<=sum(31 DOWNTO 16);
            END IF;    
        END PROCESS;
    END ARCHITECTURE logic;

    Thank you for your help !

    --- Quote End ---

    There are some misunderstandings from you.

    1)You only need add leading zeros to sum final result and not inputs to adder as you did.

    2)why divide back the result. you add zeros then remove them? what is the point

    for accurate result you need all bits. if you want 16 bits final output then it implies you want scaled version in which case you don't need to add zeros then remove them

    3) adding 1 is wrong. it should become zero and should not affect the result as it has lost that sort of accuracy
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Instead of asking us if it works - how about testing it yourself and learning the tools?

    --- Quote End ---

    I'm doing it Tricky. I'm using Quartus II with the university Program VWF. But I'm totally new also to it. I started with vhdl and testbench two days ago.. Also a little hint could give me the right direction.

    @Kaz, I need only 16 bit at the final sum as I have a 16 bit dac so at the output of the polynomial I MUST have a 16 bit signal.

    So as I have understood from your last post I do not need the leading zeros in the signals input of the sum and also at the output signal.. Am I right ?

    Thank you for your time !
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    @Kaz, I need only 16 bit at the final sum as I have a 16 bit dac so at the output of the polynomial I MUST have a 16 bit signal.

    So as I have understood from your last post I do not need the leading zeros in the signals input of the sum and also at the output signal.. Am I right ?

    Thank you for your time !

    --- Quote End ---

    you are right.

    with only 16 bit resolution you are dealing with scaled down result(not absolute values).

    A constant term must also be scaled down by 2^16 before entering addition and so you can just ignore it.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I'm doing it Tricky. I'm using Quartus II with the university Program VWF. But I'm totally new also to it. I started with vhdl and testbench two days ago.. Also a little hint could give me the right direction.

    --- Quote End ---

    Stop using the VWF file and write your own VHDL testbench. There are many examples on the web. With a testbench you can write code that is completly unsynthesisable as long as it gets the job done. An example for generating a clock:

    signal clk : std_logic := '0';

    clk <= not clk after 5 ns; -- a 100 MHz clock.

    This way you can control the input data using text files (using the textio library - give it a google - lots of tutorials), and monitor or even log the output to a log file.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Stop using the VWF file and write your own VHDL testbench. There are many examples on the web. With a testbench you can write code that is completly unsynthesisable as long as it gets the job done. An example for generating a clock:

    signal clk : std_logic := '0';

    clk <= not clk after 5 ns; -- a 100 MHz clock.

    This way you can control the input data using text files (using the textio library - give it a google - lots of tutorials), and monitor or even log the output to a log file.

    --- Quote End ---

    Thank you tricky. I will check also for this.