- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem is in your code - without the code, we cannot help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ] "- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
cool! thanks. I just ended up creating more states instead and it works fine.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page