128 bits hierarchical carry look-ahead adder in VHDL - vhdl

Hi I want to implement an 128 bits hierarchical carry look ahead adder but I don't know how to use levels in my implementation, in fact i don't know how to write the code. I write my code for 16 bits adder but i should use 4-bits blocks and combine them in levels. I almost know that I need 32 numbers of 4-bits blocks in level 1 and 8 numbers in level 2 and so on. However my code should be run for 128 to 256 bits operands but i don't know how to do this. please help me

if you already have 4bit adder, you should implement the hierarchical adder
with for generate statement like this:
library ieee;
use ieee.std_logic_1164.all;
entity carry_leveled is
generic(c_word_length : integer := 128;
c_adder_count : integer := c_word_length / 4 --count of adder entities to generate
);
port(
clk_i : in std_logic;
rst_i : in std_logic;
x_i : in std_logic_vector(c_word_length - 1 downto 0);
y_i : in std_logic_vector(c_word_length - 1 downto 0);
sum_o : out std_logic_vector(c_word_length - 1 downto 0)
);
end entity carry_leveled;
architecture RTL of carry_leveled is
component carry_lookahead_adder
port(
clk_i : in std_logic;
rst_i : in std_logic;
x_i : in std_logic_vector(c_word_length - 1 downto 0);
y_i : in std_logic_vector(c_word_length - 1 downto 0);
carry_i : in std_logic;
carry_out : out std_logic;
sum_o : out std_logic_vector(3 downto 0)
);
end component;
signal carry_vector : std_logic_vector(c_adder_count - 1 downto 0);
signal sum : std_logic_vector(c_word_length - 1 downto 0);
begin
sum_o <= sum;
carry_lookahead_adder_inst_0 : component carry_lookahead_adder
port map(clk_i => clk_i,
rst_i => rst_i,
x_i => x_i(c_adder_count - 1 downto 0),
y_i => y_i(c_adder_count - 1 downto 0),
carry_i => '0',
carry_out => carry_vector(0),
sum_o => sum(c_adder_count - 1 downto 0));
carry_look_adder_generate : for i in 1 to c_adder_count - 1 generate
carry_lookahead_adder_inst_i : component carry_lookahead_adder
port map(clk_i => clk_i,
rst_i => rst_i,
x_i => x_i((i + 1) * c_adder_count - 1 downto i * c_adder_count),
y_i => y_i((i + 1) * c_adder_count - 1 downto i * c_adder_count),
carry_i => carry_vector(i - 1),
carry_out => carry_vector(i),
sum_o => sum((i + 1) * c_adder_count - 1 downto i * c_adder_count)
);
end generate carry_look_adder_generate;
end architecture RTL;
hope i could help you

it is easier to implement in behavioral modeling language, see the following tutorial for 16 bit and just replace the numbers for 128 bits
16 bit carry look ahead adder vhdl code

Related

4-bit counter in AHDL

I have to write 4 bit counter in AHDL.
I haven't had contact with AHDL before.
The task is:
Please implement a 4 digit counter (BCD counting) in the circuit
Cyclone IV EP3CE115F29C7 FPGA being the heart of the commissioning
system De2-115 from terasic.
The counter should work with a 1Hz clock to be able to observe the change of states
display in development kit.
The outputs of the seven-segment decoders should be connected to the appropriate
FPGA pins to enable display control.
The final program should allow FPGA programming and observations
counter counting.
I have something similar in VHDL. Can you guys can help me how to rewrite this to altera?
Is there any converter maybe? I saw something like this but only from AHDL to VHDL.
I will be grateful for all the tips.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end entity bcd_counter;
architecture behaviour of bcd_counter is
signal state : unsigned (2 ** width - 1 downto 0);
begin
output <= std_logic_vector(state);
count : process(clk, reset, enable)
begin
if(reset = '0') then
state <= (others=> '0');
elsif(rising_edge(clk) and enable = '1') then
state <= state + 1;
end if;
end process count;
end architecture behaviour;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter_logic is
generic (
digits : integer := 4
);
port (
clk : in std_logic;
reset : in std_logic;
output : out std_logic_vector (4 * digits - 1 downto 0)
);
end entity counter_logic;
architecture behaviour of counter_logic is
constant digitWidth : integer := 4;
signal state : std_logic_vector(digitWidth * digits -1 downto 0);
signal resetLines : std_logic_vector(digits - 1 downto 0);
signal enableLines : std_logic_vector(digits - 1 downto 0);
component bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end component;
begin
counters: for i in digits - 1 downto 0 generate
nthCounter : bcd_counter
generic map (width => digitWidth)
port map (
clk => clk,
enable => enableLines(i),
reset => resetLines(i),
--przypisanie wyjść liczników do linii
output => state((i + 1) * digitWidth - 1 downto i * digitWidth)
);
resetLines(i) <= (not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3)) or reset;
end generate counters;
--TODO: add if generate for case of single digit counter
enableLinesCondition: if digitWidth > 1 generate
lines: for i in digits - 2 downto 0 generate
enableLines(i + 1) <= not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3);
end generate lines;
end generate enableLinesCondition;
enableLines(0) <= '1';
output <= state;
end architecture behaviour;

N-bits adder/subtractor using ripple of full adders- problem with carryout

I am trying to create N-bits adder/subtractor using a ripple of full adders.
The input is N-bits A, N-bits B, and the result should be at length of 2N (it outputs ALU with 2 buses High and low of N-bits each, so I am trying to extend the signed bit).
The problem arises with carryout in subtraction. For example, when doing 3-2 (assume N=3 so that it's 011-010 and with two's compliment it's 011+110) I get 001 with carry 1. The problem is that this carry is garbage and can't be extended, but in other case it's necessary. For example, when trying do (-3)+(-3) (101+101, again N=3), then I get 010 with carry of 1. This time the carry really indicate the sign, so I would like to extend it.
Here is my code:
entity FullAdder is
Port (
A : in std_logic;
B : in std_logic;
Cin : in std_logic;
sum : out std_logic;
Cout : out std_logic
);
end FullAdder;
architecture gate of FullAdder is
begin
sum <= A xor B xor Cin ;
Cout <= (A and B) OR (Cin and A) OR (Cin and B) ;
end gate;
here is the N-bit Adder
entity NbitsAdder is
generic(N: integer := 8);
Port(
A : in std_logic_vector((N-1) downto 0);
B : in std_logic_vector((N-1) downto 0);
Cin: in std_logic;
SUM : out std_logic_vector((N-1) downto 0);
Cout : out std_logic
);
end NbitsAdder;
architecture NbitsAdderGate of NbitsAdder is
...
signal temp : std_logic_vector (N downto 0);
begin
temp (0) <= Cin;
arrrayOfFullAdders : for i in 0 to N-1 generate
adder_i: FullAdder port map ( A(i), B(i), temp(i), SUM(i), temp (i+1) );
end generate;
Cout <= temp(N); --which will be extend
end NbitsAdderGate;
And this is the ADDER or SUBTRACTOR
entity NbitsAddOrSub is
generic(N: integer := 8);
port(
A : in std_logic_vector ((N-1) downto 0);
B : in std_logic_vector ((N-1) downto 0);
addOrSub : in std_logic;
sumLo : out std_logic_vector ((N-1) downto 0);
sumHi : out std_logic_vector ((N-1) downto 0)
);
end NbitsAddOrSub;
architecture NbitsAddOrSubGate of NbitsAddOrSub is
signal tempB: std_logic_vector ( (N-1) downto 0);
signal CoutTemp: std_logic;
begin
loop1 : for i in 0 to N-1 generate
xor_i: xorGate port map ( B(i), addOrSub, tempB(i));
end generate;
theOperation : NbitsAdder generic map (N)
port map ( A => A, B => tempB, Cin => addOrSub, sum => sumLo, Cout => CoutTemp);
sumHi <= (N-1 downto 0 => CoutTemp); -- tring to extend the sign bit
end NbitsAddOrSubGate;
In signed addition the carry has no meaning. You get the sign bit from the MSB of the sum and not from the carry. In your second example there is an underflow because -3+-3 is smaller than 2^((N=3)-1), thus the result is incorrect.
To sign-extend the result you should first check the overflow/underflow conditions for signed addition. If no overflow/underflow has occured, you look at the MSB of the sum and extend that bit

RTL Hardware Design Using VHDL, Example 7.1

7.1 - Consider an Arithmetic Circuit that can perform four operations: a+b, a-b, a+1 and a-1, where a and b are 16-bit Unsigned Numbers and the desired operation is specified by a 2-bit Control Signal, ctrl.
Is it possible to design this circuit just with one adder without using sequential logic.
I designed this circuit with 2's complementary logic but i cannot add logic (a + (not b) + 1) just one adder without memory components
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Ex_7_1_b is
generic( BUS_WIDTH : integer := 16 );
port ( a : in STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
b : in STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
ctrl : in STD_LOGIC_VECTOR (1 downto 0);
y : out STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0)
);
end Ex_7_1_b;
architecture Behavioral of Ex_7_1_b is
signal adder : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_sign : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_inp_sel : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_val : unsigned(BUS_WIDTH - 1 downto 0);
signal result : unsigned(BUS_WIDTH - 1 downto 0);
begin
mux_val <= to_unsigned(0, mux_val'length) when ctrl(1) = '1' else to_unsigned(1, mux_val'length);
mux_inp_sel <= mux_val when ctrl(0) = '1' else unsigned(b);
mux_sign <= not (mux_inp_sel) when ctrl(1) = '1' else mux_inp_sel;
result <= unsigned(a) + mux_sign;
y <= std_logic_vector(result);
end Behavioral;
I designed this circuit with Renaud Pacalet contribute.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Ex_7_1_b is
generic( g_BUS_WIDTH : integer := 16 );
port (
i_a : in std_logic_vector (g_BUS_WIDTH - 1 downto 0);
i_b : in std_logic_vector (g_BUS_WIDTH - 1 downto 0);
i_ctrl : in std_logic_vector (1 downto 0);
o_y : out std_logic_vector (g_BUS_WIDTH - 1 downto 0)
);
end Ex_7_1_b;
architecture RTL of Ex_7_1_b is
signal r_A_Ext, r_B_Ext : unsigned(g_BUS_WIDTH downto 0);
signal r_Carry_In : std_logic;
signal r_Adder : unsigned(g_BUS_WIDTH - 1 downto 0);
signal w_Mux_Inv : unsigned(g_BUS_WIDTH - 1 downto 0);
signal w_Mux_Sel : unsigned(g_BUS_WIDTH - 1 downto 0);
signal r_Result : unsigned(g_BUS_WIDTH downto 0);
begin
r_A_Ext <= unsigned(i_a & '1');
w_Mux_Sel <= to_unsigned(1, w_Mux_Sel'length) when i_ctrl(1) = '1' else unsigned(i_b);
w_Mux_Inv <= not (w_Mux_Sel) when i_ctrl(0) = '1' else w_Mux_Sel;
r_Carry_In <= '1' when i_ctrl(0) = '1' else '0';
r_B_Ext <= w_Mux_Inv & r_Carry_In;
r_Result <= r_A_Ext + r_B_Ext;
o_y <= std_logic_vector(r_Result(g_BUS_WIDTH downto 1));
end RTL;
The solution you found yourself is fine but it uses a 17-bits adder instead of a 16-bits one. With smart enough synthesizers it should not make any difference. Just for completeness here is another, 16-bits (and slightly simpler), solution:
architecture RTL of Ex_7_1_b is
signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
begin
x <= unsigned(i_a);
y0 <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
y1 <= not y0 when i_ctrl(0) = '1' else y0;
o_y <= std_logic_vector(x + y1 + i_ctrl(0));
end architecture RTL;
Note: this works only in VHDL 2008 where the addition of an unsigned and a std_logic is defined. If you must use an older version of the VHDL standard use the following, instead:
architecture RTL of Ex_7_1_b is
signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
signal c: natural range 0 to 1;
begin
x <= unsigned(i_a);
y0 <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
y1 <= not y0 when i_ctrl(0) = '1' else y0;
c <= 1 when i_ctrl(0) = '1' else 0;
o_y <= std_logic_vector(x + y1 + c);
end architecture RTL;

Using for loop to design adder in vhdl

I'm trying to create an m bit adder by instantiating multiple copies of the n bit adder using for/generate loop. This is my code so far, it fails to simulate by giving the error:
"Line 44: Not all partial formals of a_n have actual". The n bit adder is declared as component, I have successfully tested it and it works.
Please help by offering any suggestions to solve this problem
entity m_bit_adder is
generic (m : integer := 16; n : integer := 4);
Port ( A_m : in STD_LOGIC_VECTOR (m-1 downto 0);
B_m : in STD_LOGIC_VECTOR (m-1 downto 0);
Cin_m : in STD_LOGIC;
Cout_m : out STD_LOGIC;
S_m : out STD_LOGIC_VECTOR (m-1 downto 0));
end m_bit_adder;
architecture Behavioral of m_bit_adder is
component n_bit_adder is
generic (n_number : integer := 4);
Port ( A_n : in STD_LOGIC_vector(n-1 downto 0);
B_n : in STD_LOGIC_vector(n-1 downto 0);
Cin_n : in STD_LOGIC;
S_n : out STD_LOGIC_vector(n-1 downto 0);
Cout_n : out STD_LOGIC);
end component;
signal sig_m : std_logic_vector (m downto 0);
begin
m_bit_adder : for j in 0 to m-1 generate
n_bit : n_bit_adder generic map (n_number => n)
port map (
A_n(n-1) => A_m(j),
B_n(n-1)=> B_m(j),
S_n(n-1) => S_m(j),
Cin_n => sig_m(j),
Cout_n => sig_m(j+1)
);
end generate;
sig_m(0) <= Cin_m;
Cout_m <= sig_m(m);
end Behavioral;
This is my code for the n adder:
entity n_bit_adder is
generic (n : integer := 4);
Port ( A_n : in STD_LOGIC_vector(n-1 downto 0);
B_n : in STD_LOGIC_vector(n-1 downto 0);
Cin_n : in STD_LOGIC;
S_n : out STD_LOGIC_vector(n-1 downto 0);
Cout_n : out STD_LOGIC);
end n_bit_adder;
architecture Behavioral of n_bit_adder is
component adder
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
Cin : in STD_LOGIC;
S : out STD_LOGIC;
Cout : out STD_LOGIC);
end component;
signal sig_n : std_logic_vector (n downto 0);
begin
n_bit_adder : for i in 0 to n-1 generate
one_bit : adder
port map (
A => A_n(i),
B => B_n(i),
S => S_n(i),
Cin => sig_n(i),
Cout => sig_n(i+1)
);
end generate;
sig_n(0) <= Cin_n;
Cout_n <= sig_n(n);
end Behavioral;
The n_bit_adder is instantiated using only a single bit of the formal side with A_n(n-1) in:
n_bit : n_bit_adder generic map (n_number => n)
port map (
A_n(n-1) => A_m(j),
....
But the component for n_bit_adder has as std_logic_vector for A_n with multiple bits in:
component n_bit_adder is
generic (n_number : integer := 4);
Port ( A_n : in STD_LOGIC_vector(n-1 downto 0);
...
So for a std_logic_vector(3 downto 0) then A_n(2 downto 0) are not used on the formal side (left side) of the mapping, which is also what the error message says in "Not all partial formals of a_n have actual".
Note also, that it looks like different names n_number and n are used in component for generic and std_logic_vector length on ports.

How to map with a 163 bit number with a 1-bit number?

I have two 163 bit numbers and and I want to map with the multiplier. But for the multiplier, a (162 downto 0) and b is only one bit. So how can I do that? Please help.
entity demo_pointadd is
Port ( x : in STD_LOGIC_VECTOR (162 downto 0);
y : in STD_LOGIC_VECTOR(162 downto 0);
p : out STD_LOGIC_VECTOR (162 downto 0);
q : out STD_LOGIC_VECTOR (162 downto 0);
clk : in STD_LOGIC;
reset : in STD_LOGIC);
end demo_pointadd;
-- component declaration
component full_163bitmul
Port ( a : in STD_LOGIC_VECTOR (162 downto 0);
b : in STD_LOGIC;
clk : in STD_LOGIC;
reset : in STD_LOGIC;
c : out STD_LOGIC_VECTOR (162 downto 0));
end component;
begin
mul_1 :full_163bitmul
port map (a => x,
b => y, --- PROBLEM??
clk => clk,
reset => reset,
c => p);
this seems to be no multiplier by itself. when I take a guess on the code of full_163bitmul, the output 'c' will be 'a' (if b='1') or all Zeros (if b='0') or undefined (if b is 'Z' | 'X' | ...).
if you want to build a full multiplier out of it, you have to loop through 'y' vector and bring single bits to 'b' input and add-and-shift the results.
sig_b<=y(i);
mul_1 :full_163bitmul
port map
(a => s_x,
b => sig_b,
clk => clk,
reset => reset,
c => temp);
...

Resources