Signed Adder without overflow

N

Nemesis

Hi all,
I have to implement a 24 bit signed adder. I have two 2's
complement numbers on 24, and I'd like to get their sum on 25 bit signed
(2's complement). I already tried the Xilinx IP Adder core, but I'd like
to implement this adder in VHDL.

I wrote this module:

**********************************************************************
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;

entity adder24 is
port (
A : in STD_LOGIC_VECTOR(23 downto 0);
B : in STD_LOGIC_VECTOR(23 downto 0);
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR(24 downto 0)
);
end adder24;

architecture Behavioral of adder24 is
begin
----------------------------------------------------------------
process (CLK,RESET)
variable A_INT : SIGNED (23 downto 0);
variable B_INT : SIGNED (23 downto 0);
variable OUTPUT_VAR : SIGNED (24 downto 0);
begin
if RESET='1' then
OUTPUT <= "0000000000000000000000000";
elsif CLK='1' and CLK'event then
A_INT :=SIGNED(A);
B_INT :=SIGNED(B);
OUTPUT_VAR := A_INT + B_INT;
OUTPUT <= STD_LOGIC_VECTOR(OUTPUT_VAR);
end if;
end process;
----------------------------------------------------------------
end Behavioral;
**********************************************************************

I'm able to synthesize it (I get a warning on the OUTPUT_VAR size) but
modelsim returns me this error:

Length of actual is 24. Length of expected is 25.

so I can't simulate it.

How can I write a 24bit adder with a 25bit output, and with input and
output signed?
 
W

Weng Tianxiang

Changes you should made:

variable A_INT : SIGNED (24 downto 0);
variable B_INT : SIGNED (24 downto 0);
variable OUTPUT_VAR : SIGNED (24 downto 0);
begin
if RESET='1' then
OUTPUT <= "0000000000000000000000000";
elsif CLK='1' and CLK'event then
A_INT :=SIGNED(A(23) & A);
B_INT :=SIGNED(B(23) & B);
OUTPUT_VAR := A_INT + B_INT;

A(23) & A is to sign-extend A while keeping A value unchanged.

Weng
 
N

Nemesis

Mentre io pensavo ad una intro simpatica "Weng Tianxiang" scriveva:
Changes you should made:

variable A_INT : SIGNED (24 downto 0);
variable B_INT : SIGNED (24 downto 0);
variable OUTPUT_VAR : SIGNED (24 downto 0);
begin
if RESET='1' then
OUTPUT <= "0000000000000000000000000";
elsif CLK='1' and CLK'event then
A_INT :=SIGNED(A(23) & A);
B_INT :=SIGNED(B(23) & B);
OUTPUT_VAR := A_INT + B_INT;

A(23) & A is to sign-extend A while keeping A value unchanged.


Thank you very much, I just tried your code and it seems to work
correctly. Tomorrow I'll test it better.
 
A

Andy Peters

Nemesis said:
Hi all,
I have to implement a 24 bit signed adder. I have two 2's
complement numbers on 24, and I'd like to get their sum on 25 bit signed
(2's complement). I already tried the Xilinx IP Adder core, but I'd like
to implement this adder in VHDL.

I wrote this module:

**********************************************************************
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;

DON'T use std_logic_arith, and especially don't use both
std_logic_unsigned and std_logic_signed at the same time! Use
numeric_std instead.
entity adder24 is
port (
A : in STD_LOGIC_VECTOR(23 downto 0);
B : in STD_LOGIC_VECTOR(23 downto 0);
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR(24 downto 0)
);
end adder24;

architecture Behavioral of adder24 is
begin
----------------------------------------------------------------
process (CLK,RESET)
variable A_INT : SIGNED (23 downto 0);
variable B_INT : SIGNED (23 downto 0);
variable OUTPUT_VAR : SIGNED (24 downto 0);
begin
if RESET='1' then
OUTPUT <= "0000000000000000000000000";
elsif CLK='1' and CLK'event then
A_INT :=SIGNED(A);
B_INT :=SIGNED(B);
OUTPUT_VAR := A_INT + B_INT;
OUTPUT <= STD_LOGIC_VECTOR(OUTPUT_VAR);
end if;
end process;
----------------------------------------------------------------
end Behavioral;
**********************************************************************

I'm able to synthesize it (I get a warning on the OUTPUT_VAR size) but
modelsim returns me this error:

Length of actual is 24. Length of expected is 25.

so I can't simulate it.

How can I write a 24bit adder with a 25bit output, and with input and
output signed?

Simply sign-extend A and B:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder24 is
port (
A : in STD_LOGIC_VECTOR(23 downto 0);
B : in STD_LOGIC_VECTOR(23 downto 0);
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR(24 downto 0));
end entity adder24;

architecture math of adder24 is

adder : process (CLK, RESET) is
variable a_s : signed(A'high+1 downto 0);
variable b_s : signed(B'high+1 downto 0);
variable sum : signed(A'high+1 downto 0);
begin
if RESET = '1' then
OUTPUT <= (others => '0');
elsif rising_edge (CLK) then
a_s := resize(signed(A), a_s'length);
b_s := resize(signed(B), b_s'length);
sum := a_s + b_s;
OUTPUT <= std_logic_vector(sum);
end if;
end process adder;
end architecture math;
 
N

Nemesis

Mentre io pensavo ad una intro simpatica "Andy Peters" scriveva:
DON'T use std_logic_arith, and especially don't use both
std_logic_unsigned and std_logic_signed at the same time! Use
numeric_std instead.

I tried everything ;-)
However with your hint on using numeric_std I found an interesting
web-site that explains the differences betwen
numeric_std, std_logic_arith ... and so on.
Simply sign-extend A and B:
[cut]

Thanks, I liked your solution very much.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top