Have JUST started learning how to use this tool so if my question seems silly i apologize in advance. I have searched the error in numerous forums (already answered posts , not mine) and couldn't understand what i was doing wrong so here is my question:
My Behavioral Code:
----------------------------------------------------------------------------- -----
-- Company:
-- Engineer:
--
-- Create Date: 01:47:22 07/07/2015
-- Design Name:
-- Module Name: Module_1 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------- -----
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned valuessss
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Module_1 is
port (A,B,WE,reset : in std_logic;
clk : in std_logic;
DIN : in signed(3 downto 0);
FULL,EMPTY,ERROR : out std_logic:= '0';
PARKFREE : out signed(3 downto 0)
);
end Module_1;
architecture Behavioral of Module_1 is
signal current_state,next_state:std_ulogic_vector(1 downto 0);
signal empty_bf, full_bf :std_ulogic;
signal enter, reset_b : std_ulogic := '0' ;
constant s0: std_ulogic_vector (1 downto 0):="00";
constant s1: std_ulogic_vector (1 downto 0):="10";
constant s2: std_ulogic_vector (1 downto 0):="11";
constant s3: std_ulogic_vector (1 downto 0):="01";
signal park_counter,buffr: signed(3 downto 0):="0000";
signal PARKTOTAL,free_park_counter: signed(3 downto 0):= "1111";
begin
p1: process (clk,reset,reset_b)
begin
if (reset = '1') then
current_state <= s0;
elsif clk'event and clk = '1' then
current_state <= next_state;
end if;
end process p1;
p2: process (current_state,A,B)
begin
next_state <= current_state;
case current_state is
when s0 =>
if A = '1' then
enter <= '1';
next_state <= s1;
elsif B = '1' then
next_state <= s3;
end if;
when s1 =>
if A = '0' then
enter <= '0';
next_state <= s0;
elsif B = '1' then
next_state <= s2;
end if;
when s2 =>
if A = '0' then
next_state <= s3;
elsif B = '0' then
next_state <= s1;
end if;
when s3 =>
if B = '0' then
enter <= '0';
next_state <= s0;
elsif A = '1' then
next_state <= s2;
end if;
when others =>
end case;
end process p2;
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
max: process(WE)
begin
if clk'event and clk = '1' and WE = '1' then
PARKTOTAL <= DIN ;
buffr <= DIN ;
if (free_park_counter < buffr - park_counter) then
ERROR <= '1';
reset_b <= '1';
else free_park_counter <= buffr - park_counter;
end if;
end if;
end process max;
incr: process(free_park_counter,DIN)
begin
PARKFREE <= free_park_counter;
if (free_park_counter = 15) then
EMPTY <= '1';
empty_bf <= '1';
else EMPTY <= '0';
empty_bf <= '0';
end if;
if (free_park_counter = 0) then
FULL <= '1';
full_bf <= '1';
else FULL <= '0';
full_bf <= '0';
end if;
end process incr;
end Behavioral;
My Testbench
----------------------------------------------------------------------------- ---
-- Company:
-- Engineer:
--
-- Create Date: 02:17:07 07/11/2015
-- Design Name:
-- Module Name: D:/Users/ErgasiaFPGA/Testbench.vhd
-- Project Name: ErgasiaFPGA
-- Target Device:
-- Tool versions:
-- Description:
--
-- VHDL Test Bench Created by ISE for module: Module_1
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY Testbench IS
END Testbench;
ARCHITECTURE behavior OF Testbench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Module_1
PORT(
A : IN std_logic;
B : IN std_logic;
WE : IN std_logic;
reset : IN std_logic;
clk : IN std_logic;
DIN : IN signed(3 downto 0);
FULL : OUT std_logic;
EMPTY : OUT std_logic;
ERROR : OUT std_logic;
PARKFREE : OUT signed(3 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic := '0';
signal B : std_logic := '0';
signal WE : std_logic := '0';
signal reset : std_logic := '0';
signal clk : std_logic := '0';
signal DIN : signed(3 downto 0) := (others => '0');
--Outputs
signal FULL : std_logic;
signal EMPTY : std_logic;
signal ERROR : std_logic;
signal PARKFREE : signed(3 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Module_1 PORT MAP (
A => A,
B => B,
WE => WE,
reset => reset,
clk => clk,
DIN => DIN,
FULL => FULL,
EMPTY => EMPTY,
ERROR => ERROR,
PARKFREE => PARKFREE
);
-- 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 100 ns.
reset <= '1' ;
wait for 100 ns;
reset <= '0' ;
wait for clk_period*10;
-- insert stimulus here
A <= '1' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '0' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '1' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
A <= '0' ;
wait;
end process;
END;
I posted the whole code just in case i'm missing something in some part of it that i wouldn't think about. So , when i ISim it , with any "succesful" trigger of p3...
Referencing it again here:
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
...the ISim says that in this part
"There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)."
and proceeds to make Xs of some of the values after that part , although all of the signals have been initialized (at least the ones in this part)
The "park_counter <= park_counter + 1;" part works correctly in the simulation but the "free_park_counter <= free_park_counter -1;" doesn't. This completely baffles me as they are declared as the same type and are both initialized the same way , even with different values.
So what am i missing or even doing blatantly wrong? Any help will be incredibly appreciated. Only looking for the error , if you could please contain optimizations since i'm looking to learn through trial and error and thought and would like to struggle to make it better myself
In addition , please be patient with my responses since i log on 2 to 3 times per day. Thanks in advance
Your design is non-workable per Brian's answer. Your testbench causes the messages when going from s3 or s1 to s0 before the clock edge. free_park_counter goes to 'U'
s. (Once it gets U'
s it won't loop further, no events occur without a signal value change).
Your counters should be clocked to prevent combinatorial looping, plus they likely won't synthesize a clock usefully due to uneven combinatorial delays. Sensitivity lists should likewise be complete, if for no other reason than the intent is to make simulation match the synthesized result.
Looking at the result of your testbench:
We can compare that with the messages from the arithmetic operators found in the Synopsys package std_logic_arith:
../../../src/synopsys/std_logic_arith.vhdl:315:20:@350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:@350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:@550ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
The signals displayed in the waveform are selected in order of importance and appearance a first pass selection and we immediately see we also get 'U'
s on free_park_counter
as well as ERROR
.
ERROR
catches attention because you hadn't mentioned it previously. When asking 'where to the 'U'
come from ?' it becomes apparent the issue is there are drivers on ERROR
and free_park_counter
in both processes p3
and max
. The messages are a side effect.
Each process assigning a signal provides a driver. Signals with multiple drivers are either resolved or result in an error for non-resolved types.
The resolved value of free_park_counter
with one or more elements having a metavalue will cause the diagnostic messages produced by package std_logic_arith. The 'U'
s in the waveform are caused by the resolution of the two drivers.
The difficulty your audience had in noticing the two drivers may be in part due to your strong insistence on focusing on process p3
, which is not well specified. The title and focus of your question also seems a bit unclear. Without a Minimal Complete and Verifiable example there was also bound to be less scrutiny.
You might expect as a minimum to consolidate all the assignments to ERROR
and free_park_counter
into a single process. ERROR
should likely be registered, and I'd expect something named park_counter
would likely want to be registered, too.