VHDL 4-bit multiplier based on 4-bit adder - vhdl

i am a bit new to VHDL and i try to learn by examples. So long story short i began with some basic examples like creating this Full Adder.
entity FA is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
Cin : in STD_LOGIC;
S : out STD_LOGIC;
Cout : out STD_LOGIC);
end FA;
architecture gate_level of FA is
begin
S <= A XOR B XOR Cin ;
Cout <= (A AND B) OR (Cin AND A) OR (Cin AND B) ;
end gate_level;
After that i tried to implement this 4-bit adder
And this is the code that i wrote.
entity Ripple_Adder is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0);
Cout : out STD_LOGIC);
end Ripple_Adder;
architecture Behavioral of Ripple_Adder is
-- Full Adder VHDL Code Component Decalaration
component FA
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
Cin : in STD_LOGIC;
S : out STD_LOGIC;
Cout : out STD_LOGIC);
end component;
-- Intermediate Carry declaration
signal c1,c2,c3: STD_LOGIC;
begin
-- Port Mapping Full Adder 4 times
FA1: FA port map( A(0), B(0), Cin, S(0), c1);
FA2: FA port map( A(1), B(1), c1, S(1), c2);
FA3: FA port map( A(2), B(2), c2, S(2), c3);
FA4: FA port map( A(3), B(3), c3, S(3), Cout);
end Behavioral;
Also i used a 4_bit_adder test bench file and i found out that the output is right. Now i am trying to implement a 4 bit multiplier with the usage of the 4 bit adder but i am a bit stuck. Actually this is the multiplier that i am trying to implement.
the code i wrote is this, but i am stuck at the port map
--library
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_textio.all;
use IEEE.std_logic_unsigned.all;
--entity
entity multy is
port (x: in std_logic_vector(3 downto 0);
y: in std_logic_vector(3 downto 0);
p : out std_logic_vector(7 downto 0)
);
end multy ;
-- architecture
architecture rtl of multy is
component Ripple_Adder
Port ( A : in std_logic_vector (3 downto 0);
B : in std_logic_vector (3 downto 0);
Cin : in std_logic;
S : out std_logic_vector (3 downto 0);
Cout : out std_logic);
end component ;
signal andgate: std_logic_vector(15 downto 0);
signal sumout: std_logic_vector( 11 downto 0);
signal carry: std_logic_vector(11 downto 0);
begin
andgate(0) <= x(0) and y(0);
andgate(1) <= x(1) and y(0); --b0
andgate(2) <= x(2) and y(0); --b1
andgate(3) <= x(3) and y(0); --b2
B
andgate(4) <= x(0) and y(1);
andgate(5) <= x(1) and y(1);
andgate(6) <= x(2) and y(1);
andgate(7) <= x(3) and y(1);
andgate(8) <= x(0) and y(2);
andgate(9) <= x(1) and y(2);
andgate(10) <= x(2) and y(2);
andgate(11) <= x(3) and y(2);
andgate(12) <= x(0) and y(3);
andgate(13) <= x(1) and y(3);
andgate(14) <= x(2) and y(3);
andgate(15) <= x(3) and y(3);
--gates
cell_1: Ripple_Adder port map();
cell_2: Ripple_Adder port map();
cell_3: Ripple_Adder port map();
--Assigning p values
p(0) <= andgate(0);
p(1) <= sumout(0);
p(2) <= sumout(4);
p(3) <= sumout(8);
p(4) <= sumout(9);
p(5) <= sumout(10);
p(6) <= sumout(11);
p(7) <= carry(11);
end rtl ;

"I am stuck on the port map" isn't a specific problem statement.
With named association members of formal ports in maps could be associated individually as well as in whole as long as all members of the formal are associated - IEEE Std 1076-2008 6.5.7 Association lists:
A formal interface object shall be either an explicitly declared interface object or member (see 5.1) of such an interface object. In the former case, such a formal is said to be associated in whole. In the latter cases, named association shall be used to associate the formal and actual; the subelements of such a formal are said to be associated individually. Furthermore, every scalar subelement of the explicitly declared interface object shall be associated exactly once with an actual (or subelement thereof) in the same association list, and all such associations shall appear in a contiguous sequence within that association list. Each association element that associates a slice or subelement (or slice thereof) of an interface object shall identify the formal with a locally static name.
Note you have too many carry elements (only need two), don't need andgate(0), don't need sumout(0), sumout(4) or sumout(11 downo 8), there's an extraneous character in the multy architecture, you're missing context clauses and have unused use clauses.
Your code using array intermediary signals:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_textio.all; -- NOT USED
-- use ieee.std_logic_unsigned.all; -- NOT USED
entity multy is
port (
x: in std_logic_vector (3 downto 0);
y: in std_logic_vector (3 downto 0);
p: out std_logic_vector (7 downto 0)
);
end entity multy;
architecture rtl of multy is
component Ripple_Adder
port (
A: in std_logic_vector (3 downto 0);
B: in std_logic_vector (3 downto 0);
Cin: in std_logic;
S: out std_logic_vector (3 downto 0);
Cout: out std_logic
);
end component;
-- AND Product terms:
signal G0, G1, G2: std_logic_vector (3 downto 0);
-- B Inputs (B0 has three bits of AND product)
signal B0, B1, B2: std_logic_vector (3 downto 0);
begin
-- y(1) thru y (3) AND products, assigned aggregates:
G0 <= (x(3) and y(1), x(2) and y(1), x(1) and y(1), x(0) and y(1));
G1 <= (x(3) and y(2), x(2) and y(2), x(1) and y(2), x(0) and y(2));
G2 <= (x(3) and y(3), x(2) and y(3), x(1) and y(3), x(0) and y(3));
-- y(0) AND products (and y0(3) '0'):
B0 <= ('0', x(3) and y(0), x(2) and y(0), x(1) and y(0));
-- named association:
cell_1:
Ripple_Adder
port map (
a => G0,
b => B0,
cin => '0',
cout => B1(3), -- named association can be in any order
S(3) => B1(2), -- individual elements of S, all are associated
S(2) => B1(1), -- all formal members must be provide contiguously
S(1) => B1(0),
S(0) => p(1)
);
cell_2:
Ripple_Adder
port map (
a => G1,
b => B1,
cin => '0',
cout => B2(3),
S(3) => B2(2),
S(2) => B2(1),
S(1) => B2(0),
S(0) => p(2)
);
cell_3:
Ripple_Adder
port map (
a => G2,
b => B2,
cin => '0',
cout => p(7),
S => p(6 downto 3) -- matching elements for formal
);
p(0) <= x(0) and y(0);
end architecture rtl;
And a borrowed testbench to demonstrate:
library ieee;
use ieee.std_logic_1164.all;
entity multy_tb is -- testbench
end entity;
architecture foo of multy_tb is
signal x, y: std_logic_vector (3 downto 0);
signal yp, rp: std_logic_vector (7 downto 0);
use ieee.numeric_std.all;
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
DUT:
entity work.multy
port map (
x => x,
y => y,
p => yp
);
STIMULI:
process
begin
for i in 0 to 15 loop
x <= std_logic_vector(to_unsigned(i, x'length));
for j in 0 to 15 loop
y <= std_logic_vector(to_unsigned(j, y'length));
wait for 0 ns; -- assignments take effect
rp <= std_logic_vector(unsigned (x) * unsigned(y));
wait for 10 ns;
if yp /= rp then
report "multy error";
report HT & "expected " & to_string (rp);
report HT & "got " & to_string (yp);
end if;
end loop;
end loop;
wait;
end process;
end architecture;
The to_string function is included for pre -2008 simulators. Context clauses were added to FA and Ripple_Adder.

Related

Error with VHDL port mapping an adder with unsigned variables

So i made a 4 bit adder, and I wanted it port mapped to an ALU I am building, yet for some reason the port map is coming up as an error. I have tried everything, changing variable types, changing the logic, and even changing variable names, but nothing works. The error pops up when I try to use the port map (the lines where it says bit0, bit1...), and the error complains about the work 'port' and ';'.
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
use ieee.numeric_std.all;
-- Define the input and output signals
ENTITY bit_FA IS
PORT (
A, B : in unsigned(7 downto 0);
CI : in std_logic;
SUM : out unsigned(7 downto 0);
CO : out std_logic);
END bit_FA;
-- Describe the full adder 's behavior
ARCHITECTURE bit_FA1 OF bit_FA IS
signal tmp: unsigned(8 downto 0);
begin
tmp <= A + B + ("0" & ci); --trick to promote ci to unsigned
SUM <= tmp(7 downto 0);
CO <= tmp(8);
END bit_FA1;
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.numeric_std.ALL;
-- Define the input and output signals
ENTITY FinalLab IS
PORT (
CLK : in BIT;
code : in BIT_VECTOR;
A: in STD_LOGIC_VECTOR (3 downto 0);
B : inout STD_LOGIC_VECTOR (3 downto 0);
C, D : out STD_LOGIC_VECTOR (3 downto 0);
CO : out STD_LOGIC);
END FinalLab;
ARCHITECTURE behave_1 OF FinalLab IS
signal cin : std_logic_vector(3 downto 0);
component bit_FA is
port (
a, b, c : in std_logic;
sum, carry : out std_logic);
end component;
BEGIN
process(code)
begin
if code = "000" then
--error
bit0 : bit_FA port map( A(0), B(0), '0', C(0), cin(0));
bit1 : bit_FA port map ( A(1), B(1), carry(0), C(1), cin(1) );
bit2 : bit_FA port map ( A(2), B(2), carry(1), C(2), cin(2) );
bit3 : bit_FA port map ( A(3), B(3), carry(2), C(3), cin(3) );
CO <= cin(3);
elsif code = "001" then
C(0) <= A(3);
C(1) <= A(2);
C(2) <= A(1);
C(3) <= A(0);
elsif code = "010" then
--multiplication
B <= std_logic_vector( unsigned(B) - 1 );
elsif code = "011" then
C <= std_logic_vector( unsigned(A) + 1 );
elsif code = "100" then
C(0) <= not(A(0) XOR B(0));
C(1) <= not(A(1) XOR B(1));
C(2) <= not(A(2) XOR B(2));
C(3) <= not(A(3) XOR B(3));
elsif code = "101" then
C(0) <= not A(0);
C(1) <= not A(1);
C(2) <= not A(2);
C(3) <= not A(3);
elsif code = "110" then
C(0) <= A(3);
C(1) <= A(0);
C(2) <= A(1);
C(3) <= A(2);
elsif code = "111" then
C(0) <= A(1);
C(1) <= A(2);
C(2) <= A(3);
C(3) <= A(0);
end if;
end process;
END behave_1;
VHDL stands for VHSIC Hardware Description Language. As it is hardware, you cannot use if-statements and such to make components magically appear and disappear. All components need to be connected all the time.
What you can do is implement switched/multiplexers to select the output of components. However, you need intermediate signals.
I.e., the full adders need to be connected in the architecture scope and the output selected in the if statement
ARCHITECTURE behave_1 OF FinalLab IS
signal FA_out : std_logic_vector(3 downto 0);
[...]
begin
bit0 : bit_FA port map( A(0), B(0), '0', FA_out(0), cin(0));
bit1 : bit_FA port map ( A(1), B(1), cin(0), FA_out(1), cin(1) );
bit2 : bit_FA port map ( A(2), B(2), cin(1), FA_out(2), cin(2) );
bit3 : bit_FA port map ( A(3), B(3), cin(2), FA_out(3), cin(3) );
[...]
if code = "000" then
C <= FA_out;
CO <= cin(3);
[...]
Note: the CLK input port is there for a reason... use it.

VHDL Waveform Simulation Line/Spikes Anomaly

I'm currently building a n-bit subtractor, and it appears to be working fine, but my waveform has these anomalous lines that instantaneously come and go. I'm not sure what's causing them, and it's been bugging me for days. You can see the spikes happening for the "negative" signal - I suspect it's because of some concurrency issue but I have tried searching all kinds of keywords to find the root of this problem and haven't come up with anything:
Code:
One bit full adder
library ieee;
use ieee.std_logic_1164.all;
entity one_bit_full_adder is
port (
x, y, cin : in std_logic;
sum, cout: out std_logic);
end one_bit_full_adder;
architecture arch of one_bit_full_adder is
begin
sum <= x xor y xor cin;
cout <= (x and y) or (cin and (x xor y));
end arch;
N-bit subtractor
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity n_bit_subtractor is
generic(constant BIT_LENGTH : integer);
port (
a, b : in std_logic_vector(BIT_LENGTH - 1 downto 0);
negative: out std_logic;
difference: out std_logic_vector(BIT_LENGTH - 1 downto 0));
end n_bit_subtractor;
architecture arch of n_bit_subtractor is
component one_bit_full_adder port (x, y, cin: in std_logic; sum, cout: out std_logic); end component;
signal carry_ins: std_logic_vector(BIT_LENGTH downto 0) := (0 => '1', others => '0');
signal differences: std_logic_vector(BIT_LENGTH - 1 downto 0);
signal b_operand: std_logic_vector(BIT_LENGTH - 1 downto 0);
begin
b_operand <= not b;
difference <= differences;
negative <= differences(BIT_LENGTH - 1) and '1';
adders: for i in 0 to BIT_LENGTH-1 generate
H2: one_bit_full_adder port map(x=>a(i), y=>b_operand(i), cin=>carry_ins(i), sum=>differences(i), cout=>carry_ins(i+1));
end generate;
end arch;
Testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity n_bit_subtractor_test is
end n_bit_subtractor_test;
architecture arch_test of n_bit_subtractor_test is
constant BIT_LEN : integer := 3;
component n_bit_subtractor is
generic(constant BIT_LENGTH : integer);
port (
a, b : in std_logic_vector(BIT_LENGTH - 1 downto 0);
negative: out std_logic;
difference: out std_logic_vector(BIT_LENGTH - 1 downto 0));
end component n_bit_subtractor;
signal p0, p1, difference: std_logic_vector(BIT_LEN-1 downto 0) := (others => '0');
signal negative: std_logic;
begin
uut: n_bit_subtractor
generic map (BIT_LENGTH => BIT_LEN)
port map (a => p0, b => p1, difference => difference, negative => negative);
process
variable difference_actual: std_logic_vector(BIT_LEN-1 downto 0) := (others => '0');
begin
for i in 0 to (2**BIT_LEN)-1 loop
for k in 0 to (2**BIT_LEN)-1 loop
wait for 200 ns;
p1 <= std_logic_vector(unsigned(p1) + 1);
end loop;
p0 <= std_logic_vector(unsigned(p0) + 1);
end loop;
report "No errors detected. Simulation successful." severity failure;
end process;
end arch_test;
Any help would be greatly appreciated. The ModelSim version is v10.1d

Avoid using inout in VHDL

I want to avoid using inout at the following code.
Is there any way I can do it? For example a helping signal?
entity LA_Unit is
Port ( Cin : in STD_LOGIC;
P : in STD_LOGIC_VECTOR (3 downto 0);
G : in STD_LOGIC_VECTOR (3 downto 0);
C3 : out STD_LOGIC;
C : inout STD_LOGIC_VECTOR (2 downto 0));
end LA_Unit;
architecture Behavioral of LA_Unit is
begin
C(0) <= (P(0) and Cin) xor G(0);
C(1) <= (P(1) and C(0)) xor G(1);
C(2) <= (P(2) and C(1)) xor G(2);
C3 <= (P(3) and C(2)) xor G(3);
end Behavioral;
If the purpose is simply to provide the intermediate value of C as an output to the module, there are different options to avoid inout.
If the tools support VHDL-2008, you can simply change inout to out, and then the C can still be read internally.
If the tools only support VHDL-2002, then you can still change the inout to out, but you then need an internal signal like:
architecture Behavioral of LA_Unit is
signal C_int : std_logic_vector(2 downto 0);
begin
C_int(0) <= (P(0) and Cin) xor G(0);
C_int(1) <= (P(1) and C_int(0)) xor G(1);
C_int(2) <= (P(2) and C_int(1)) xor G(2);
C3 <= (P(3) and C_int(2)) xor G(3);
C <= C_int;
end Behavioral;
As xvan also write, only use inout for toplevel ports on the chip, or for special test-bench use, since inout are not supported internally in a chip.
Use a signal as an intermediate for C(0) and C(1).
Inouts should only be used for hardware io ports, like a gpio port, or the data port on a memory bus.
There are 2 solutions:
Using buffer mode instead of inout.
entity LA_Unit is
Port ( Cin : in STD_LOGIC;
P : in STD_LOGIC_VECTOR (3 downto 0);
G : in STD_LOGIC_VECTOR (3 downto 0);
C3 : out STD_LOGIC;
C : buffer STD_LOGIC_VECTOR (2 downto 0));
end LA_Unit;
architecture Behavioral of LA_Unit is
begin
C(0) <= (P(0) and Cin) xor G(0);
C(1) <= (P(1) and C(0)) xor G(1);
C(2) <= (P(2) and C(1)) xor G(2);
C3 <= (P(3) and C(2)) xor G(3);
end Behavioral;
Some tools have problems with this mode.
An intermediate signal:
entity LA_Unit is
Port ( Cin : in STD_LOGIC;
P : in STD_LOGIC_VECTOR (3 downto 0);
G : in STD_LOGIC_VECTOR (3 downto 0);
C3 : out STD_LOGIC;
C : out STD_LOGIC_VECTOR (2 downto 0)
);
end entity;
architecture rtl of LA_Unit is
signal C_i : STD_LOGIC_VECTOR(3 downto 0);
begin
C_i(0) <= (P(0) and Cin) xor G(0);
C_i(1) <= (P(1) and C_i(0)) xor G(1);
C_i(2) <= (P(2) and C_i(1)) xor G(2);
C_i(3) <= (P(3) and C_i(2)) xor G(3);
C <= C_i(2 downto 0);
C3 <= C_i(3);
end architecture

8 bit Ripple carry adder Port mappinng in VHDL

I wrote the code for 8 bit adder by usign 4 bit carry look ahead adder. i instantiated the 4 bit caryy look ahed adder using port map. but i think i am wrong for port mapping . plese any one can hel me , how can i correct the port mapping ..
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity adder_4_bit is
Port ( a,b : in STD_LOGIC_VECTOR (3 downto 0);
s : out STD_LOGIC_VECTOR (3 downto 0);
cout: out STD_LOGIC);
end adder_4_bit;
architecture Behavioral of adder_4_bit is
signal g, p, c, b1: STD_LOGIC_VECTOR(3 downto 0);
begin
g <= a and b;
p <= a xor b;
s(0) <= p(0) ;
c(0) <= g(0) or p(0) ;
s(1) <= p(1) xor c(0);
c(1) <= g(1) or (p(1) and g(0)) or (p(1) and p(0));
s(2) <= p(2) xor c(1);
c(2) <= g(2) or (p(2) and g(1)) or (p(2) and p(1) and g(0)) or (p(2) and p(1) and p(0));
s(3) <= p(3) xor c(2);
c(3) <= g(3) or (p(3) and g(2)) or (p(3) and p(2) and g(1)) or (p(3) and p(2) and p(1) and g(0)) or (p(3) and p(2) and p(1) and p(0));
cout <= c(3);
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--********************************************************--
entity Adder_8_bit is
Port (
a,b : in STD_LOGIC_VECTOR (7 downto 0);
s : out STD_LOGIC_VECTOR (7 downto 0);
cout: out STD_LOGIC
);
end Adder_8_bit;k
---******************---
architecture Behavioral of Adder_8_bit is
component adder_4_bit is
Port (
A,B : in STD_LOGIC_VECTOR (3 downto 0);
S: out STD_LOGIC_VECTOR (3 downto 0);
cout: out STD_LOGIC
);
end component;
----
signal a1 ,b1 : STD_LOGIC_VECTOR (7 downto 0);
signal SUM : STD_LOGIC_VECTOR (7 downto 0);
begin
four_bit_adder1: adder_4_bit port map ( a1(3 downto 0) ,b1(3 downto 0) , SUM (3 downto 0) , cout) ;
four_bit_adder2: adder_4_bit port map ( a1(7 downto 4) ,b1(7 downto 4) , SUM (7 downto 4) , cout ) ;
end Behavioral;
You connect the signal cout to two drivers:
four_bit_adder1: adder_4_bit port map ( a1(3 downto 0) ,b1(3 downto 0) , SUM (3 downto 0) , cout);
four_bit_adder2: adder_4_bit port map ( a1(7 downto 4) ,b1(7 downto 4) , SUM (7 downto 4) , cout );
This is wrong, as the toplevel cout should have only 1 source, in this case the four_bit_adder2.
Your 4 bits adder also requires a carry in, otherwise it is impossible to chain two of them to form a 8 bits adder. The first adder's carry in is '0', the second adder's carry in is the first adder's carry out.

VHDL Adder Test Bench

I'm new to VHDL and I'm making a 4bit adder using 4 Full Adders. I created a test bench to see if the adder is working and in the ans I'm getting values of UUUU. From what I read is that the process is not being executed. I have no idea how to fix this, any help would be appreciated.
Here is the TestBench
ENTITY Adder4_Test IS
END Adder4_Test;
ARCHITECTURE behavior OF Adder4_Test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Adder4
PORT(
X : IN STD_LOGIC_vector(3 downto 0);
Y : IN STD_LOGIC_vector(3 downto 0);
Ans : OUT STD_LOGIC_VECTOR(3 downto 0);
Cout : OUT STD_LOGIC
);
END COMPONENT;
--Inputs
signal X : STD_LOGIC_vector(3 downto 0) := (others => '0');
signal Y : STD_LOGIC_vector(3 downto 0) := (others => '0');
--Outputs
signal Ans : STD_LOGIC_vector(3 downto 0);
signal Cout : STD_LOGIC;
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
--constant <clock>_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Adder4 PORT MAP (
X,
Y,
Ans,
Cout
);
-- Clock process definitions
--<clock>_process :process
--begin
--<clock> <= '0';
--wait for <clock>_period/2;
--<clock> <= '1';
--wait for <clock>_period/2;
--end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
--wait for 100 ns;
--wait for <clock>_period*10;
-- insert stimulus here
-- Case 1 that we are testing.
X <= "0000";
Y <= "0000";
wait for 10 ns;
assert ( Ans = "0000" )report "Failed Case 1 - Ans" severity error;
assert ( Cout = '0' ) report "Failed Case 1 - Cout" severity error;
wait for 40 ns;
-- Case 2 that we are testing.
X <= "1111";
Y <= "1111";
wait for 10 ns;
assert ( Ans = "1110" )report "Failed Case 2 - Ans" severity error;
assert ( Cout = '1' ) report "Failed Case 2 - Cout" severity error;
wait for 40 ns;
wait;
end process;
END;
Here is the Adder4
entity Adder4 is
Port ( X : in STD_LOGIC_vector (3 DOWNTO 0);
Y : in STD_LOGIC_vector (3 DOWNTO 0);
Ans: out STD_LOGIC_vector (3 DOWNTO 0);
Cout: out STD_LOGIC);
end Adder4;
architecture Structure of Adder4 is
component FullAdder is
Port ( X : in STD_LOGIC;
Y : in STD_LOGIC;
Cin : in STD_LOGIC;
Sum : out STD_LOGIC;
Cout : out STD_LOGIC);
end component;
signal c0, c1, c2, c3: STD_LOGIC;
begin
c0 <='0';
b_adder0: FullAdder port map (X(0), Y(0), c0, Ans(0), c1);
b_adder1: FullAdder port map (X(1), Y(1), c1, Ans(1), c2);
b_adder2: FullAdder port map (X(2), Y(2), c2, Ans(2), c3);
b_adder3: FullAdder port map (X(3), Y(3), c3, Ans(3), Cout);
end Structure;
Here is the FullAdder
entity FullAdder is
Port ( X : in STD_LOGIC;
Y : in STD_LOGIC;
Cin : in STD_LOGIC;
Sum : out STD_LOGIC;
Cout : out STD_LOGIC);
end FullAdder;
architecture Behavioral of FullAdder is
component Xor_Model is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
C : in STD_LOGIC;
Z : out STD_LOGIC);
end component;
begin
Cout <= ((X and Y) or (Y and Cin) or (X and Cin));
Sum <= (X AND (NOT Y) AND (NOT Cin)) OR ((NOT X) AND Y AND (NOT Cin)) OR
((NOT X) AND (NOT Y) AND Cin) OR (X AND Y AND Cin) after 5ns;
xorLabel: Xor_Model
Port Map ( A => X, B => Y, C => Cin, Z => Sum);
end Behavioral;
After adding context clauses you didn't supply, separating 5ns into 5 ns and insuring the entities needed in Addr4 were analyzed in the right order, I tried to run a simulation using ghdl where I promptly got an error message"
Adder4.vhdl:28:1:warning: component instance "xorlabel" is not bound
Adder4.vhdl:12:15:warning: (in default configuration of fulladder(behavioral))
This for the FullAdder. Seeing it was a 3 input XOR, I added one:
library ieee;
use ieee.std_logic_1164.all;
entity Xor_model is
Port (A: in std_logic;
B: in std_logic;
C: in std_logic;
Z: out std_logic
);
end entity;
architecture behavioral of Xor_model is
begin
Z <= A xor B xor C;
end behavioral;
There were 'U's on ans until 5 ns, from the Sum assignment delay in FullAdder.
I got 'X's at 50 ns on ans cleared 5 ns later from the same delayed assignment. Notice the LSB is '0' due to a short circuit logical operator.
Adding FF to FF got FE (correct without regards to carryout which showed up correctly as '1').
Getting rid of the initial 'U's could be done one of two ways. Either assign a known value to Sum as a default value instead of relying on the default, or removing the delay in the assignment to Sum.
The 'X's are dependent on Sum from the FullAdders as well, there are transitions on inputs while waiting for 5 ns.
In a behavioral combinatoric model delays aren't particularly expressive, in particular when you don't use delays for sub terms. If you delay contributing signals all along then signal path for a particular net based on gate delays, Sum would show up at the correct cumulative delay time. You could also use an intermediary Sum (with a different signal name) generated without delay and assign it to the output port Sum after a delay, eliminating the 'X's. Move the after 5 ns from FullAdder to Adder4:
In FullAdder:
((NOT X) AND (NOT Y) AND Cin) OR (X AND Y AND Cin) ; --after 5 ns;
In Adder4:
architecture Structure of Adder4 is
signal sum: std_logic_vector(3 downto 0);
b_adder0: FullAdder port map (X(0), Y(0), c0, sum(0), c1);
b_adder1: FullAdder port map (X(1), Y(1), c1, sum(1), c2);
b_adder2: FullAdder port map (X(2), Y(2), c2, sum(2), c3);
b_adder3: FullAdder port map (X(3), Y(3), c3, sum(3), Cout);
And add delay assigning sum to the ans:
Ans <= sum after 5 ns;
And where if you set a default value of '0's on Ans in the Adder4 port:
Ans: out STD_LOGIC_vector (3 DOWNTO 0) := (others => '0');
You can get rid of the initial 'U's:
And to clarify the 'U's are there until there is a transaction on the output (Ans) following the after 5 ns delay. It might be more proper to use (others => 'X')

Resources