Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

std_logic_vector won't accept certain values

I was asked to design a simple can dispensing machine using VHDL.I have an input called CoinIn and is defined as an std_logic_vector(1 downto 0);for some reason, when I try to force it with a "11" it will treat it as a "01" and when i try to force it with a "10" it will treat it at "00" (meaning that the CoinIn[0] is always connected to ground) .Does anyone have any idea what the problem might be?(I use Modelsim Student Edition for simulating)

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Sorry.. My bad. Here is the code and the .do file (at the buttom):

    library ieee;

    use ieee.std_logic_1164.all;

    ENTITY FSM IS

    PORT (CLK : in std_logic; --Clock, active high

    RSTn : in std_logic; --Async. Reset, active low

    CoinIn : in std_logic_vector (1 downto 0) ; --Which coin was inserted

    Soda : out std_logic := '0'; --Is Soda dispensed ?

    CoinOut : out std_logic_vector (1 downto 0) --Which coin is dispensed?

    );

    END ENTITY;

    ARCHITECTURE behavior of FSM IS

    TYPE state IS ( start, change, can, pending );

    SIGNAL present_state, next_state : state;

    SIGNAL Count : integer range 0 to 6:=0;

    BEGIN

    PROCESS (RSTn, clk, CoinIn) --sync part

    BEGIN

    IF RSTn ='0' THEN

    present_state <= start;

    ELSIF rising_edge(clk) THEN

    present_state <= next_state;

    END IF;

    END PROCESS;

    PROCESS (CoinIn, clk, present_state, next_state) --combinational

    VARIABLE SodaVar : std_logic;

    VARIABLE CoinOutVar : std_logic_vector(1 downto 0);

    BEGIN

    CoinOutVar := "00";

    CASE present_state is

    WHEN start =>

    SodaVar := '0';

    IF CoinIn = "01" then

    next_state <= pending;

    count <= 1;

    ELSIF CoinIn = "10" then

    next_state <= can;

    count <= 0;

    ELSIF CoinIn = "11" then

    next_state <= change;

    count <= 5;

    ELSIF CoinIn = "00" THEN

    next_state <= start;

    count <= 0;

    END IF;

    WHEN pending =>

    SodaVar := '0';

    IF CoinIn = "01" then

    next_state <= can;

    count <= 2;

    ELSIF CoinIn = "10" then

    next_state <= change;

    count <= 3;

    ELSIF CoinIn = "11" then

    next_state <= change;

    count <= 6;

    ELSIF CoinIn = "00" then

    next_state <= pending;

    END IF;

    WHEN change =>

    SodaVar := '0';

    IF ((count - 2) = 1) then

    CoinOutVar := "01";

    count <= 0;

    next_State <= can;

    ELSIF ((count -2) = 0) then

    next_state <= can;

    count <= 0;

    CoinOutVar := "00";

    ELSE

    next_state <= change;

    count <= count - 2;

    CoinOutVar := "10";

    END IF;

    WHEN can =>

    next_state <= start;

    SodaVar := '1';

    count <= 0;

    END CASE;

    Soda <= SodaVar;

    CoinOut <= CoinOutVar;

    END PROCESS;

    END ARCHITECTURE;

    ------ THE DO FILE

    transcript off

    echo "------- START OF MACRO -------"

    onerror abort

    restart -force

    noview *

    add wave *

    view signals

    ;# ====== start of stimulus section ======

    force clk 0 , 1 50 ns -r 100 ns

    force rstn 0

    run 100

    force rstn 1

    force coinin 11

    run 50 ns

    force coinin 00

    ;# ======= end of stimulus section=======

    echo "------- END OF MACRO -------"

    echo "The time now is $now [ string trim $resolution 01 ] "
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Instead of using force as your testbench, I highly suggest writing a VHDL testbench for you simulation. It will teach you more and give you more control.

    I have run your macro and code, and I also dont quite understand (I never use the force command, and I dont know anyone that does)

    A couple of notes on your code:

    You count signal will be created with as a latch as it is not assigned in every state.

    Also, you cannot implement the count signal inthe asynchronous state machine process as you have a subtractor in there. The code as it is will not match the real hardware - to get real hardware count must be in the sensitivity list, and you will notice you will get yourself into an infinite loop, as count will constantly try and subtract 2 from itself (as will occur in real hardware). You cannot have counters in asynchronous processes, they must be synchronous.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you very much for your reply.

    I'm not sure I understood - were you able to assign values other than 00 and 01 to CoinIn?

    Are you suggesting that the problem is caused because I used force rather than a TB?

    About the counter - thanks for explaining. How would you suggest implementing it then?

    Will moving the counting feature under the rising_edge condition work?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    With the current .do file, it does assign "01" to Coin in when it should be "11".

    I dont know what the problem is exactly, Im sure someone with better modelsim knowledge would know. But I do know that "force" is not a recommended way of generating test signals. It is ok for very simple setups, but when you get any form of complexity a testbench has far more control (eg read stimulus from file, log file generation, trasaction based stimulus etc, constrained random testing).

    If I was going to recommend anything, it would be to ditch the two process state machine style, and go with a single clocked process. It avoids latches completly as everything will have a registered output. The two process style is valid, but it's method is taught because tools many years ago would only accept this style, and the old text books linger. The single process style has been acceptable for at least 10 years.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    here is an example of a single process state machine:

    
    process(clk, reset)
    begin
        if reset = '1' then
            current_state <= idle;
            count         <= 0;
            
        elsif rising_edge(clk) then
        
            case current_state is
                when idle =>
                    if input = '1' then
                        current_state <= doing_something;
                    end if;
                
                when doing_something =>
                    count <= count + 1;
                    
                    if count = SOME_NUMBER then
                        current_state <= finished;
                    end if;
                    
                when finished =>
                    
                    count <= 0;
                    current_state <= idle;
            end case;
        end if;
    end process;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    cool! thanks. I just ended up creating more states instead and it works fine.