Forum Discussion

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

Signed Addition in VHDL

Hi everyone,

I want to implement an addition operation using VHDL. I have one input that comes from my Nios. this value is calculated in float format, then it sent to the VHDL block that i want to implement.

to sent this value to vhdl block using internal connection, I use this :

union position
{ 
 alt_32   I_position;
 float F_position;
 }; 

FI_position.F_position =float_value;
Posit_mask=FI_position.I_position;
IOWR_ALTERA_AVALON_PIO_DATA(REGISTRE_POSITION_BASE,Posit_mask);

In the VHDL side, this value becomes
Position_In: in std_logic_vector(31 downto 0);

So, the description of the algorithm is as follows:
Result_now= Position_In + Result_before.

To do this i convert all values to be signed. My vhdl program looks like this :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library altera_mf;
USE altera_mf.all;
-- Add the library and use clauses before the design unit declaration
 
library altera;
use altera.altera_primitives_components.all;
Entity Sum_Position is 
   Generic ( Accu_lenght : integer  -- in µs 
             ); 
    port 
    
    (
      Clk: in std_logic;
      Reset: in std_logic;
      Raz_position: in std_logic;
      Position_In: in std_logic_vector(Accu_lenght-1 downto 0);
      Position_Out: out std_logic_vector(Accu_lenght-1 downto 0)
    );
end Sum_Position;
Architecture Arch_position of sum_Position is 
signal position_before: signed (Accu_lenght-1 downto 0):= (OTHERS => '0');
-- both signals have one more bit than the original
signal Position_s   : SIGNED(Accu_lenght downto 0):= (OTHERS => '0');
signal Position_Before_s   : SIGNED(Accu_lenght downto 0):= (OTHERS => '0');
signal Sum_Pos_s : SIGNED(Accu_lenght downto 0):= (OTHERS => '0');
signal temp        : std_logic_vector(2 downto 0):= (OTHERS => '0');
Begin  -- begin of architecture
-- convert type and perform a sign-extension
Position_s <=resize(signed(Position_In), Position_s'length);
Position_Before_s <= resize(signed(position_before), Position_Before_s'length);
Sum_of_position: process(Clk, Reset) 
begin 
  
  IF (Reset='0') THEN            -- when reset is selected
  -- initialize all values 
     Sum_Pos_s<= (OTHERS => '0');
  ELSIF (Clk'event and Clk = '1') then
     -- addition of two 33 bit values
    Sum_Pos_s <= Position_s + Position_Before_s;
  END IF;  
end process Sum_of_position;
-- resize to require size and type conversion
position_before <= (OTHERS => '0') WHEN Raz_position='1' else  -- Reset to zero when Raz_position='1'
                                         signed(resize(Sum_Pos_s, position_before'length));
Position_Out  <= (OTHERS => '0') WHEN Raz_position='1' else  -- Reset to zero when Raz_position='1'
                             std_logic_vector(resize(Sum_Pos_s, Position_Out'length));
end Arch_position;

I create a test bench, to test my algorithm. this are the inputs to test:

     Position_In <= (OTHERS => '0');
        WAIT FOR 20 NS;
        RESET <='1';
        WAIT FOR 20 NS;
        Position_In <= X"bfa1ffd6";  -- -1,26562
        WAIT FOR 20 NS;
        Position_In <= X"41010000";  --8,0625
        WAIT FOR 20 NS;
        Position_In <= X"bf31003f";  -- -0,69141
        WAIT FOR 20 NS;
        Position_In <= X"3fb9ffd6";  -- +1,45312
        WAIT FOR 20 NS;
        Position_In <= X"c0b80000";  -- -5,75
        WAIT FOR 20 NS;
        Position_In <= X"c0f10000";  -- -7,53125
        WAIT  ;--100 NS;

I don't have the result expected, my logic is correct ?

Thank you in advance for help.

Best regards,

2 Replies

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

    You said the inputs are floating point - signed treats the value as fixed point which is fundamentally different. If you insist on floating point, you'll have to use a floating point function from the IP catalog. It uses way more logic than a fixed point adder.