VHDL Adder Test Bench - vhdl

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')

Related

16 to 1 mux using 2 to 1 mux in vhdl

I'm trying to write a code in vhdl to create a 16 to 1 mux using 2 to 1 mux.
I actually thought that to do this we may need 15 two to one multiplexers and by wiring them together and using structural model I wrote the code below.
First I wrote a 2 to 1 mux:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity MUX_2_1 is
port (
w0 , w1 : IN STD_LOGIC;
SELECT_I: IN std_logic;
DATA_O: out std_logic
);
end MUX_2_1;
architecture MUX_2_1_arch of MUX_2_1 is
--
begin
--
WITH SELECT_I SELECT
DATA_O <= w0 WHEN '0',
w1 WHEN '1',
'X' when others;
--
end MUX_2_1_arch;
and made a package from it, just to use it simple and easy:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
PACKAGE mux2to1_package IS
COMPONENT mux2to1
PORT (w0, w1: IN STD_LOGIC ;
SELECT_I: IN std_logic;
DATA_O: out std_logic ) ;
END COMPONENT ;
END mux2to1_package ;
and then my 16 to 1 mux looks like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE work.mux2to1_package.all ;
ENTITY mux16to1 IS
PORT (w : IN STD_LOGIC_VECTOR(15 DOWNTO 0) ;
s : IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
f : OUT STD_LOGIC ) ;
END mux16to1 ;
ARCHITECTURE Structure OF mux16to1 IS
SIGNAL im : STD_LOGIC_VECTOR(7 DOWNTO 0) ;
SIGNAL q : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL p : STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
Mux1: mux2to1 PORT MAP ( w(0), w(1), s(0), im(0)) ;
Mux2: mux2to1 PORT MAP ( w(2), w(3), s(0), im(1)) ;
Mux3: mux2to1 PORT MAP ( w(4), w(5), s(0), im(2)) ;
Mux4: mux2to1 PORT MAP ( w(6), w(7), s(0), im(3)) ;
Mux5: mux2to1 PORT MAP ( w(8), w(9), s(0), im(4)) ;
MUX6: mux2to1 PORT MAP ( w(10), w(11), s(0), im(5));
Mux7: mux2to1 PORT MAP ( w(12), w(13), s(0), im(6)) ;
Mux8: mux2to1 PORT MAP ( w(14), w(15), s(0), im(7)) ;
Mux9: mux2to1 PORT MAP ( im(0), im(1), s(1), q(0)) ;
Mux10: mux2to1 PORT MAP ( im(2), im(3), s(1), q(1)) ;
Mux11: mux2to1 PORT MAP ( im(4), im(5), s(1), q(2)) ;
Mux12: mux2to1 PORT MAP ( im(6), im(7), s(1), q(3)) ;
Mux13: mux2to1 PORT MAP ( q(0), q(1), s(2), p(0)) ;
Mux14: mux2to1 PORT MAP ( q(2), q(3), s(2), p(1)) ;
Mux15: mux2to1 PORT MAP ( p(0), p(1), s(3), f) ;
END Structure ;
and also my testbench is:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE work.mux2to1_package.all ;
ENTITY Mux_test IS
END Mux_test;
ARCHITECTURE test OF Mux_test IS
COMPONENT mux16to1 PORT(w : IN STD_LOGIC_VECTOR(15 DOWNTO 0) ;
s : IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
f : OUT STD_LOGIC ) ;
END COMPONENT;
SIGNAL wi : STD_LOGIC_VECTOR(15 DOWNTO 0) ;
SIGNAL selecting : STD_LOGIC_VECTOR(3 DOWNTO 0) ;
SIGNAL fi : STD_LOGIC ;
BEGIN
a1: mux16to1 PORT MAP(wi , selecting , fi);
wi<= "0101110010001010" , "1001000101010101" after 100 ns;
selecting <= "0011" , "1010" after 20 ns , "1110" after 40 ns, "1100" after 60 ns , "0101" after 80 ns,
"0011" after 100 ns , "1010" after 120 ns , "1110" after 140 ns, "1100" after 160 ns , "0101" after 180 ns;
END ARCHITECTURE;
my simulation:
But when I try to simulate this nothing shows in my output. I'm thinking that maybe that's because I wrote my code in concurrent part and signals im and q and p are not initialized yet so I tried using default values "00000000" for im and "0000" for q and "00" for p when I was declaring the signals, but then I got bunch of errors saying "Instance mux2to1 is unbound" in simulation and nothing actually changed.
Any idea what is the problem??
Also I think there is something wrong with my select input logically.
but I don't understand how i should use the select to be correct for this problem.
I would appreciate if anyone can help me with my problem.
Virtual component binding using component declarations can either be explicit using a configuration specification to supply a binding indication, or rely on a default binding indication.
A default binding indication would rely on finding an entity declared in a reference library whose name matches the component name. That's not the case here, your entity is named MUX_2_1 (case insensitive) while the component name is mux2to1.
It's not illegal to have components unbound in VHDL, it's the equivalent of not loading a component in a particular location in a printed circuit or bread board, it simply produces no output which shows in simulation here as a 'U'.
Here the solutions could be to either change the name of the entity in both the entity declaration and it's architecture from MUX_2_1 to mux2to1, change the component declaration to MUX_2_1 or provide a configuration specification providing an explicit binding indication as a block declarative item in the architecture for mux16to1 of the form
ARCHITECTURE Structure OF mux16to1 IS
SIGNAL im : STD_LOGIC_VECTOR(7 DOWNTO 0) ;
SIGNAL q : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL p : STD_LOGIC_VECTOR(1 DOWNTO 0);
for all: mux2to1 use entity work.MUX_2_1; -- ADDED
When used the latter method provides '1' and '0' outputs on testbench signal fi during simulation.
The testbench can be made more elaborate to demonstrate that the selects are valid. One way would be with marching '0's or '1's in w elements while scanning all the elements and looking for a mismatch:
library ieee;
use ieee.std_logic_1164.all;
entity mux16to1_tb is
end mux16to1_tb;
architecture test of mux16to1_tb is
component mux16to1 is
port (
w: in std_logic_vector(15 downto 0);
s: in std_logic_vector(3 downto 0);
f: out std_logic
);
end component;
signal w: std_logic_vector(15 downto 0);
signal s: std_logic_vector(3 downto 0);
signal f: std_logic;
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:
mux16to1
port map (
w => w,
s => s,
f => f
);
STIMULI:
process
use ieee.numeric_std.all;
begin
for i in w'reverse_range loop
w <= (others => '1');
w(i) <= '0';
for j in w'reverse_range loop
s <= std_logic_vector(to_unsigned(j, s'length));
wait for 10 ns;
end loop;
end loop;
wait;
end process;
VALIDATE:
process
begin
for x in w'reverse_range loop
for y in w'reverse_range loop
wait for 10 ns;
assert f = w(y)
report
LF & HT & "f = " & std_ulogic'image(f) & " " &
"expected " & std_ulogic'image(w(y)) &
LF & HT & "w = " & to_string(w) &
LF & HT & "s = " & to_string(s)
severity ERROR;
end loop;
end loop;
wait;
end process;
end architecture;
The output f of mux16to1 is selected for each value of w using a marching '0's pattern. Any mismatch between f and the selected name element value of w is reported with diagnostic information.
Here we see that mux16t01 implements a 16:1 selection properly without the need to modify the original posters design.
Without error injection the testbench waveforms for w, s and f can be viewed in a waveform display to validate correct operation.

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

procedure in VHDL returns unknown

I have to compare functional and rtl codes. The following code is written as a structural code for twoscomponent of a 16 bit input. I have tried to code the following circuit:
Here I have enclosed the code and the test-bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity two_s_complement_16bit_rtl is
Port ( A : in STD_LOGIC_VECTOR (15 downto 0);
Cout : out STD_LOGIC_VECTOR (15 downto 0):= (others => '0'));
end two_s_complement_16bit_rtl;
architecture Behavioral of two_s_complement_16bit_rtl is
procedure two_s_complement (
A : in std_logic;
B : in std_logic;
C : out std_logic;
cout : out std_logic;
cin : in std_logic) is
begin
cout := ((not A) and B) xor (((not A) xor B) and cin);
end procedure;
begin
process (A)
variable temp_C, temp_Cout: STD_LOGIC_VECTOR(15 downto 0);
constant B_0 : STD_LOGIC := '1';
constant B_1 : STD_LOGIC := '0';
begin
for i in 0 to 15 loop
if (i = 0) then
two_s_complement ( A(i), B_0 ,temp_C(i) ,temp_Cout(i) , B_1);
else
two_s_complement ( A(i), B_1 ,temp_C(i) ,temp_Cout(i) , temp_C(i-1));
end if;
end loop;
Cout <= temp_Cout;
end process;
end Behavioral;
The test-bench:
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;
entity two_s_complement_16bit_rtl_tb is
end;
architecture bench of two_s_complement_16bit_rtl_tb is
component two_s_complement_16bit_rtl
Port ( A : in STD_LOGIC_VECTOR (15 downto 0);
Cout : out STD_LOGIC_VECTOR (15 downto 0):= (others => '0'));
end component;
signal A: STD_LOGIC_VECTOR (15 downto 0);
signal Cout: STD_LOGIC_VECTOR (15 downto 0):= (others => '0');
begin
uut: two_s_complement_16bit_rtl port map ( A => A,
Cout => Cout );
stimulus: process
begin
-- Put initialisation code here
A <= "0100010010110000";
wait for 10 ns;
A <= "0011000011110111";
wait for 10 ns;
A <= "0000000000000001";
wait for 10 ns;
A <= "0011110010110011";
wait for 10 ns;
A <= "0010000100100001";
wait for 10 ns;
A <= "0001011100100011";
wait for 10 ns;
A <= "1011000110111001";
wait for 10 ns;
A <= "0000001011001010";
wait for 10 ns;
A <= "0011110110100000";
wait for 10 ns;
A <= "0100000111111000";
wait for 10 ns;
A <= "1011111001111100";
wait for 10 ns;
A <= "1111000110000001";
wait for 10 ns;
A <= "0111000111001011";
wait for 10 ns;
A <= "1011011101101010";
wait for 10 ns;
A <= "1111001001010111";
wait for 10 ns;
-- Put test bench stimulus code here
wait;
end process;
end;
I have considered three inputs for the first unit, but two of them Cin and B have their constant values as mentioned in the code, but the output is unknown.
There are three apparent errors.
First the two_s_complement procedure does not assign C which is easy to fix:
procedure
two_s_complement (
a: in std_logic;
b: in std_logic;
c: out std_logic;
cout: out std_logic;
cin: in std_logic
) is
variable inta: std_logic := not a;
begin
c := inta xor b xor cin; -- ADDED
cout := ((not a) and b) xor (((not a) xor b) and cin);
-- cout := (inta and b) or (inta and cin);
end procedure;
This is shown as a full adder with the a input inverted.
Second, you've got an incorrect association for cin in the procedure calls:
for i in 0 to 15 loop
if i = 0 then
two_s_complement (
a => a(i),
b => b_0,
c => temp_c(i),
cout => temp_cout(i),
cin => b_1
);
else
two_s_complement (
a => a(i),
b => b_1,
c => temp_c(i),
cout => temp_cout(i),
cin => temp_cout(i - 1) -- WAS temp_c(i-1)
);
end if;
The error stands out when you use named association.
Third the cout output of two_s_complement_16bit_rtl should be assigned from temp_c:
cout <= temp_c; -- WAS temp_cout;
Fixing these three things gives:
something that looks right.
The two's complement can be simplified by delivering not A to an increment circuit where all the unneeded gates are streamlined along with eliminating the B input. You'd find for instance that the LSB is never affected.

How to put desired inputs for VHDL simulation (force Command)

The Following is the VHDL code for a counter using D flip-flops. Here we are assuming the flip-flops are positive edge triggered.
Inside the architecture, I declared Q (present state) and D as a 4-Bit logic vector.
I assigned all the outputs (Z0 to Z7) and D signal values to match the logic expressions determined by the minimum input equations for the counter and flip-flops respectively.
At the end of the code a process is called to simulate the behavior of clear (ClrN) and clock (CLK)
My Question:
The code works properly but I am facing an issue with the Simulation of the test bench.
In the simulation we need to show circuit started out with the state 1000 and it then goes through each state in the correct order.
In Short: How do i show the signals Q and D in the simulation.
This is the part i am not sure on how to do.
I was told to use the force commands to set the desired inputs.
For Example:
force ClrN 0 0, 1 20
force CLK 1000 0
force CLK 0 0, 1 40 -repeat 80
But i am not sure where and how to use it.
Below is the VHDL Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity counter is
port (CLK, ClrN : in std_logic;
Z0 : out std_logic;
Z1 : out std_logic;
Z2 : out std_logic;
Z3 : out std_logic;
Z4 : out std_logic;
Z5 : out std_logic;
Z6 : out std_logic;
Z7 : out std_logic);
end counter;
architecture Behavioral of counter is
signal Q: std_logic_vector(0 to 3);
signal D: std_logic_vector(0 to 3);
begin
u1: process(Q)
begin
Z0 <= Q(0) and not Q(1) and not Q(3);
Z1 <= Q(0) and Q(1);
Z2 <= not Q(0) and Q(1) and not Q(2);
Z3 <= Q(1) and Q(2);
Z4 <= not Q(1) and Q(2) and not Q(3);
Z5 <= Q(2) and Q(3);
Z6 <= not Q(0) and not Q(2) and Q(3);
Z7 <= Q(0) and Q(3);
D(0) <= not Q(1) and not Q(2);
D(1) <= not Q(2) and not Q(3);
D(2) <= not Q(0) and not Q(3);
D(3) <= not Q(0) and not Q(1);
end process u1;
u2: process(CLK,ClrN)
begin
if ClrN = '0' then
Q <= "1000";
elsif Rising_Edge (CLK) then
Q <= D;
end if;
end process u2;
end Behavioral;
The following is my VHDL test bench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
COMPONENT counter
PORT(
CLK : IN std_logic;
ClrN : IN std_logic;
Z0 : OUT std_logic;
Z1 : OUT std_logic;
Z2 : OUT std_logic;
Z3 : OUT std_logic;
Z4 : OUT std_logic;
Z5 : OUT std_logic;
Z6 : OUT std_logic;
Z7 : OUT std_logic
);
END COMPONENT;
--Inputs
signal CLK : std_logic := '0';
signal ClrN : std_logic := '0';
--Outputs
signal Z0 : std_logic;
signal Z1 : std_logic;
signal Z2 : std_logic;
signal Z3 : std_logic;
signal Z4 : std_logic;
signal Z5 : std_logic;
signal Z6 : std_logic;
signal Z7 : std_logic;
-- Clock period definitions
constant CLK_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: counter PORT MAP (
CLK => CLK,
ClrN => ClrN,
Z0 => Z0,
Z1 => Z1,
Z2 => Z2,
Z3 => Z3,
Z4 => Z4,
Z5 => Z5,
Z6 => Z6,
Z7 => Z7
);
-- Clock process definitions
CLK_process :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- -- hold reset state for 10 ns.
wait for 10 ns;
ClrN <= '1';
wait;
end process;
END;
Where and how do I add the Q and D signals to my test bench in order to get the simulation that shows the circuit started out with the state 1000 and it then goes through each state in the correct order.
and do i even use force command?
One way to document what happens in the simulation (in addition to the waveform) is to write the desired signals into output (like printf in c) or to file (like fprintf).
To do this, first include textio package:
use std.textio.all;
use ieee.std_logic_textio.all;
and then amend you process:
u2: process(CLK,ClrN)
file f0 : text is out "output.txt";
begin
if ClrN = '0' then
Q <= "1000";
elsif Rising_Edge (CLK) then
--pragma translate_off
write(output, "Q:" & to_string(Q) & " D:" & to_string(D) & lf);
write(f0, "Q:" & to_string(Q) & " D:" & to_string(D) & lf);
--pragma translate_on
Q <= D;
end if;
end process u2;
The pragmas are not absolutely necessary, but they are a good habit to add to whatever non-synthesizable code inside a module that is meant for synthesis.
In your example, force should be used not.

VHDL : False Results in 4-Bit Adder and Subtractor

I want to make a 4-Bit Adder and Subtractor with VHDL
I have created 1-Bit Full-Adder , XOR Gate ( for Subtract ) and a 4-Bit Adder as shown below :
Full-Adder :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY FullAdder_1_Bit IS
PORT(
X, Y : IN STD_LOGIC;
CIn : IN STD_LOGIC;
Sum : OUT STD_LOGIC;
COut : OUT STD_LOGIC
);
END FullAdder_1_Bit;
ARCHITECTURE Behavier OF FullAdder_1_Bit IS
BEGIN
Sum <= X XOR Y XOR CIn;
COut <= (X AND Y) OR (X AND CIn) OR (Y AND CIn);
END Behavier;
XOR Gate :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY XORGate IS
PORT(
X1, X2 : IN STD_LOGIC;
Y : OUT STD_LOGIC
);
END XORGate;
ARCHITECTURE Declare OF XORGate IS
BEGIN
Y <= X1 XOR X2;
END Declare;
4-Bit Adder :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END Adder_4_Bit;
ARCHITECTURE Structure OF Adder_4_Bit IS
COMPONENT FullAdder_1_Bit IS
PORT(
X, Y : IN STD_LOGIC;
CIn : IN STD_LOGIC;
Sum : OUT STD_LOGIC;
COut : OUT STD_LOGIC
);
END COMPONENT;
COMPONENT XORGate IS
PORT(
X1, X2 : IN STD_LOGIC;
Y : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL COut_Temp : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL XB : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
B_0 : XORGate PORT MAP(Mode, B(0), XB(0));
B_1 : XORGate PORT MAP(Mode, B(1), XB(1));
B_2 : XORGate PORT MAP(Mode, B(2), XB(2));
B_3 : XORGate PORT MAP(Mode, B(3), XB(3));
SUM_0 : FullAdder_1_Bit
PORT MAP (A(0), XB(0), Mode, Sum(0), COut_Temp(0));
SUM_1 : FullAdder_1_Bit
PORT MAP (A(1), XB(1), COut_Temp(0), Sum(1), COut_Temp(1));
SUM_2 : FullAdder_1_Bit
PORT MAP (A(2), XB(2), COut_Temp(1), Sum(2), COut_Temp(2));
SUM_3 : FullAdder_1_Bit
PORT MAP (A(3), XB(3), COut_Temp(2), Sum(3), COut);
END;
and in my Main Codes , i have used those ( like Test-Bench ! ) :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY Add_AND_Sub IS
END Add_AND_Sub;
ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
Add : Adder_4_Bit
PORT MAP(XA, XB, Mode, Sum, E);
PROCESS(A, B, Mode)
BEGIN
As <= A(4);
Bs <= B(4);
XA <= A(3 DOWNTO 0);
XB <= B(3 DOWNTO 0);
CASE Mode IS
WHEN '0' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '1';
XA <= Sum;
AVF <= '0';
IF (E = '1') THEN
IF (XA = "0000") THEN
As <= '0';
END IF;
ELSE
XA <= (NOT XA) + "0001";
As <= NOT As;
END IF;
ELSE
XA <= Sum;
END IF;
WHEN '1' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '0';
XA <= Sum;
AVF <= E;
ELSE
AVF <= '0';
XA <= Sum;
IF (E = '1') THEN
IF (XA = "0000") THEN
As <= '0';
END IF;
ELSE
XA <= (NOT XA) + "0001";
As <= NOT As;
END IF;
END IF;
WHEN Others =>
--
END CASE;
END PROCESS;
END Declare;
The main scenario is to Model this algorithm :
but now i want to have output in XA and As
I Should use registers shown in algorithm such as "E" and "AVF"
there is one question :
we know port maps are continuously connected , so when i change Mode Value , Result ( Sum ) must change , is it True ?!
I have tried this code but i cant get output in XA , and there is no True result for sum values , i know there is some problem in my main code ( Process ) , but i cant find problems
please check that codes and tell me what goes wrong !
Edit :
Im using ModelSim and its simulation for testing my code , first i force values of "A", "B" and "Mode" then run to get result and wave
thanks ...
Your testbench add_and_sub makes no assignments to it's a and b, they're default values are all 'U's.
What do you expect when your inputs to adder_4_bit are undefined?
Look at the not_table, or_table, and_table and xor_table in the body of the std_logic_1164 package.
Also to be a Minimal, Complete, and Verifiable example your readers need both expected and actual results.
If you're actually simulating the testbench I'd expect it consume no simulation time and after some number of delta cycles during initialization show sum and e chock full of 'U's.
I haven't personally modified your testbench to determine if your adder_4_bit works, but if you provide it with valid stimulus you can debug it. It can be helpful to consume simulation time and use different input values.
Adding a monitor process to add_and_sub:
MONITOR:
process (sum)
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;
-- report "image_str = " & image_str;
return image_str;
end;
begin
report "sum = " & to_string(sum);
end process;
gives:
fourbitadder.vhdl:174:10:#0ms:(report note): sum = uuuu
one event on sum.
Add a process to cause events on a and 'b`:
STIMULUS:
process
begin
a <= "00000" after 10 ns;
b <= "00000" after 10 ns;
wait for 20 ns;
wait;
end process;
and we get:
(clickable)
We find we get an event on a and b but sum didn't change.
And the reason why is apparent in the case statement in the process. The default value of mode is 'U', and the case statement has choices for 0, 1 and:
when others =>
--
end case;
And the others choice results in no new value in mode.
Why nothing works can be discovered by reading the source of the body for package std_logic_1164, the xor_table, and_table, or_table. With mode = 'U' all your combinatorial outputs will be 'U'.
And to fix this you can assign a default value to mode where it is declared in the testbench:
signal mode : std_logic := '0';
With mode defined as a valid choice resulting in some action we note xa is now never defined causing the same issue:
(clickable)
And this is a problem in the process:
process(a, b, mode)
begin
as <= a(4);
bs <= b(4);
xa <= a(3 downto 0);
xb <= b(3 downto 0);
case mode is
when '0' =>
if ((as xor bs) = '1') then
mode <= '1';
xa <= sum;
avf <= '0';
if (e = '1') then
if (xa = "0000") then
as <= '0';
end if;
else
xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
as <= not as;
end if;
else
xa <= sum;
end if;
when '1' =>
if ((as xor bs) = '1') then
mode <= '0';
xa <= sum;
avf <= e;
else
avf <= '0';
xa <= sum;
if (e = '1') then
if (xa = "0000") then
as <= '0';
end if;
else
xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
as <= not as;
end if;
end if;
when others =>
--
end case;
Notice there are three places where xa is assigned, with no simulation time between them. There's only one projected output waveform value for any simulation time. A later assignment in the same process will result in the later value being assigned, in this case sum, which is all 'U's.
So how do you solve this conundrum? There are two possibilities. First you could not try and do algorithmic stimulus generation, assigning input to add explicitly with wait statements between successive assignments of different values. You can also insert delays between successive assignments to the same signal in the existing process, which requires a substantial re-write.
On a positive note the adder_4_bit and full_adder_1bit look like they should work. The problem appears to be all in the testbench.
I made some changes
I made a ALU unit as :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY ALU IS
PORT(
--Clk : IN STD_LOGIC;
A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
Sel : IN STD_LOGIC;
AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
AsO : OUT STD_LOGIC
);
END ALU;
ARCHITECTURE Declare OF ALU IS
COMPONENT Adder_4_Bit IS
PORT(
A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Mode : IN STD_LOGIC;
Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
COut : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
BEGIN
Add : Adder_4_Bit
PORT MAP(XA, XB, Mode, Sum, E);
PROCESS
BEGIN
As <= A(4);
Bs <= B(4);
XA <= A(3 DOWNTO 0);
XB <= B(3 DOWNTO 0);
CASE Sel IS
WHEN '0' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '1';
AVF <= '0';
WAIT ON Sum;
IF (E = '1') THEN
IF (Sum = "0000") THEN
As <= '0';
END IF;
ELSE
Sum <= (NOT Sum) + "0001";
As <= NOT As;
END IF;
ELSE
Mode <= '0';
WAIT ON Sum;
END IF;
AOut <= Sum;
AsO <= As;
WHEN '1' =>
IF ((As XOR Bs) = '1') THEN
Mode <= '0';
WAIT ON Sum;
AVF <= E;
ELSE
Mode <= '1';
WAIT ON Sum;
AVF <= '0';
IF (E = '1') THEN
IF (Sum = "0000") THEN
As <= '0';
END IF;
ELSE
Sum <= (NOT Sum) + "0001";
As <= NOT As;
END IF;
END IF;
AOut <= Sum;
AsO <= As;
WHEN Others =>
--
END CASE;
END PROCESS;
END Declare;
and A Test Bench like this :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;
ENTITY ALU_Test_Bench IS
END ALU_Test_Bench;
ARCHITECTURE Declare OF ALU_Test_Bench IS
COMPONENT ALU IS
PORT(
--Clk : IN STD_LOGIC;
A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
Sel : IN STD_LOGIC;
AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
AsO : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL Xs, S : STD_LOGIC;
SIGNAL X, Y, O : STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
ALU_PM : ALU PORT MAP(X, Y, S, O, Xs);
Main_Process : PROCESS
BEGIN
WAIT FOR 100 ns;
X <= "00010";
Y <= "11011";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
WAIT FOR 100 ns;
X <= "01110";
Y <= "10011";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
WAIT FOR 100 ns;
X <= "10011";
Y <= "11111";
S <= '0';
WAIT FOR 30 ns;
S <= '1';
WAIT FOR 30 ns;
END PROCESS;
END Declare;
As i say , i want to model the algorithm i posted in first post
there is some problem ...
for example when i simulate and run test bench , there is no output value in O and Xs !
I know the problem is in ALU and Test Bench
I changed ALU many times and tested many ways but all times some things goes wrong !
If you want to code that algorithm , which units you will create or at all what will you create ?! and how will you code that ?!
thanks for your help ...

Resources