Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17250 Discussions

std_logic_vector won't accept certain values

Altera_Forum
Honored Contributor II
1,720 Views

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)

0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
892 Views

The problem is in your code - without the code, we cannot help.

0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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 ] "
0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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?
0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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;
0 Kudos
Altera_Forum
Honored Contributor II
892 Views

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

0 Kudos
Reply