1

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

stonedevil
  • 45
  • 1
  • 5
  • Experimenting with the code , i now have the following observation to make: Made the values of park_counter and free_park_counter the same ("0000") , made them both increment at p3 when my testbench instantiates that situation and declared them at the same line. park_counter works , free_park_counter does the same thing as before. I feel this is getting silly ,anyone have any idea? – stonedevil Jul 11 '15 at 19:22

3 Answers3

1

There is some confusion in the question title : declaring a signal and setting its value are entirely separate.

Initialising a signal (in the declaration) will influence its value, but not fully determine it. If the initialisation and another driving value are different, the result probably will be 'X'. Likewise if the signal is driven from different processes which disagree on its value.

Now, you are using a multiple-process form of state machine, where the operations are split between clocked and combinational processes. These are recommended by more than one textbook. This is unfortunate because they are notoriously difficult to get right, and for example, a moment's inspection will show that the sensitivity list on process P3 is wrong.

Fixing P3's sensitivity list may not affect the problem, because P3 also drives its own inputs in what is known as a combinational loop. Consider that, if the process wakes up several times because of glitches on the combinational inputs in its sensitivity list, the additions will take place several times...

Rewriting these three processes in the form of a single clocked process P1, (which is, unfortunately, not well taught in several textbooks) will avoid all of these difficulties.

  • He has deficiencies in four sensitivity lists. Fixing those (without consolidating processes), switching to package numeric_std (a clean substitution) and writing a testbench I didn't get any messages. That suggests the question isn't a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). How to replicate the problem? The glitches and multiple additions might be cured with `postponed` but you'd really expect counters should be clocked. There appear to be various other inferred latches. –  Jul 11 '15 at 10:35
  • @Brian indeed the title is written horribly , had to realize it when you pointed it out , was very tired and frustrated about the whole idea so i got careless , sorry. You are probably right when you say that this can be done way cleaner if done in one process but i want to know what is going on with these types of errors in general , if only to avoid them in future projects of any kind and understand the idea behind it in general. If i fail , i will probably switch to 1 function indeed. Could you please explain how P3 drives its inputs? It only changes internal signals values – stonedevil Jul 11 '15 at 12:06
  • @user1155120 I'm only now learning these things but as i understand in your comment , you are pretty much saying that you changed a bunch of things and now can't replicate my problem? What happens pretty much is after the "when s3 =>" of p3 successfully completes and does the "free_park_counter <= free_park_counter - plus;", the value in the sim turns from 1111 to 111X. Additionally , after activating the first part , the now 111X will turn to XXXX. That's what happens. If you would think that i should also post the testbench please tell me to do so. I didn't think it would be of any use – stonedevil Jul 11 '15 at 12:13
  • "Could you please explain how P3 drives its inputs?" Yes. `park_counter <= park_counter - plus;` Correct P3's sensitivity list and this executes an infinite number of times, chasing its own tail. (And yes, post the testbench. As the other comment says, it's an essential part of a Minimal Complete Verifiable Example. –  Jul 11 '15 at 12:16
  • You may find this Q&A helpful in the backstory of signal assignments, process scheduling, and sensitivity lists. http://stackoverflow.com/questions/13954193/is-process-in-vhdl-reentrant/13956532#13956532 –  Jul 11 '15 at 12:22
  • Posted the testbench as well , got completely rid of the "plus" and used +1 / -1 in its place. Thanks to both of you guys for pointing out the testbench should be posted , didn't know that although i can understand why it should be so – stonedevil Jul 11 '15 at 13:04
  • "executes an infinite number of times" Once free_park_counter goes to a metavalue it will not loop, events are changes in value. –  Jul 11 '15 at 22:38
1

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:

stonedevil.png (clickable)

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.

  • @Brian Took me about a week but i read through ALL of the article(s) posted by Brian and i think i got a better understanding of every aspect of what's going on , it's at least more complex than i thought at first. I must thank you guys both for pretty much educating me on some basic level (which i didn't in any case have) but since user1155120 gave the answer to my original question , i'm picking this one. Don't get me wrong in any case , you guys have my deepest appreciation – stonedevil Jul 16 '15 at 15:17
0

In ISim, if you browse the tree menu on the left you are able to add to then signals window any internal signal you want. Add all of them, rerun the simulation and look for the signals that have 'U'|'X'|'W'|'Z'|'-' values. This should give us a lead to track down the problem.

If you are really new to VHDL, this answer of mine should help you undersand some of the basic concepts of this description language :) VHDL - iSIM output uninitialised, doesn't change states

Another advice that I learned the hard way, but you can think about it after we solved this problem: textbooks and even Xilinx describe how to implement finite state machines with two or even three distinct processes. This comes from an educational approach where FSM are splitted in synchronous logic and asynchronous logic. In practice, this is doing more harm than good: most of the FSM can be described with a single synchronous process. Google it (or if you are interested we can talk about it) and try it, you will get the hang of it really quickly and it will really simplify the code (you won't even need two separate signals for the states anymore!).

FlyerDragon
  • 212
  • 4
  • 16
  • That's where i got my values from , have added most of the values to the waveform and see where they change and how. That's pretty much how i try and debug the whole code. Probably will switch to using only one process for the sake of functionality but this errors baffles and i would very much like to undestand why it happens. If you would like , check the comment on the above post in response to user1155120 to see what happens with the values. Additionally , i would like to say that i have also tried the addition / subtraction with immediated as in:free_park_counter <= free_park_counter - 1;" – stonedevil Jul 11 '15 at 12:18
  • forgot to mention that when this happens , the values are already set. Pretty much all values are set. But when the "free_park_counter <= free_park_counter -1;" comes along , it goes from 1111 to 111X and i can't figure out why for the life of me – stonedevil Jul 11 '15 at 17:35