简体   繁体   中英

Xilinx / ISim seem claims value to be X but it has been declared

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

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.

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.

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!).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM