From: KMS on
On Dec 1 2009, 11:53 am, "glallenjr" <glalle...(a)gmail.com> wrote:
> Currently I am studying the "Circuit Design with VHDL" by Volnei A.
> Pedroni. On page 207 the run a simulation but do not provide the test
> bench. I would like to run the same simulation but I am not familiar with
> how to write a testbench. If possible please provide a testbench to mimic
> the simulation shown on page 207. If you are unfamiliar with this book or
> the simulation run, I would also appreciate ANY KIND of testbench which
> could simulate it's funcionality. Also if there are any errors with the
> code, please let me know! Your help is much appreciated! thank you!
>
> Here is the code we are trying to implement:
>
> library IEEE;
> use IEEE.STD_LOGIC_1164.ALL;
>
> entity vending_machine is
>     Port ( clk, rst : IN  STD_LOGIC;
>            nickel_in, dime_in, quarter_in : IN  BOOLEAN;
>            candy_out, nickel_out, dime_out, quarter_out: OUT STD_LOGIC);
> end vending_machine;
>
> architecture fsm of vending_machine IS
>         TYPE state IS (st0, st5, st10, st15, st20, st25, st30, st35, st40, st45);
>         SIGNAL present_state, next_state: STATE;
>
> begin
>         PROCESS(rst, clk)
>         BEGIN
>                 IF(rst='1') THEN
>                         present_state <=st0;
>                 ELSIF(clk' EVENT AND clk ='1') THEN
>                         present_state <= next_state;
>                 END IF;
>         END PROCESS;
>
>         PROCESS(present_state, nickel_in, dime_in, quarter_in)
>         BEGIN
>                 CASE present_state IS
>                         WHEN st0 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 IF (nickel_in) THEN next_state <= st5;
>                                 ELSIF (dime_in) THEN next_state <= st10;
>                                 ELSIF (quarter_in) THEN next_state <= st25;
>                                 ELSE next_state <=st0;
>                                 END IF;
>                         WHEN st5 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 IF (nickel_in) THEN next_state <= st10;
>                                 ELSIF (dime_in) THEN next_state <= st15;
>                                 ELSIF (quarter_in) THEN next_state <= st30;
>                                 ELSE next_state <=st5;
>                                 END IF;
>                         WHEN st10 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 IF (nickel_in) THEN next_state <= st15;
>                                 ELSIF (dime_in) THEN next_state <= st20;
>                                 ELSIF (quarter_in) THEN next_state <= st35;
>                                 ELSE next_state <=st10;
>                                 END IF;
>                         WHEN st15 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 IF (nickel_in) THEN next_state <= st20;
>                                 ELSIF (dime_in) THEN next_state <= st25;
>                                 ELSIF (quarter_in) THEN next_state <= st40;
>                                 ELSE next_state <=st15;
>                                 END IF;
>                         WHEN st20 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 IF (nickel_in) THEN next_state <= st25;
>                                 ELSIF (dime_in) THEN next_state <= st30;
>                                 ELSIF (quarter_in) THEN next_state <= st45;
>                                 ELSE next_state <=st20;
>                                 END IF;
>                         WHEN st25 =>
>                                 candy_out <= '1';
>                                 nickel_out <='0';
>                                 dime_out <= '0';
>                                 next_state <= st0;
>                         WHEN st30 =>
>                                 candy_out <= '1';
>                                 nickel_out <='1';
>                                 dime_out <= '0';
>                                 next_state <= st0;
>                         WHEN st35 =>
>                                 candy_out <= '1';
>                                 nickel_out <='0';
>                                 dime_out <= '1';
>                                 next_state <= st35;
>                         WHEN st45 =>
>                                 candy_out <= '0';
>                                 nickel_out <='0';
>                                 dime_out <= '1';
>                                 next_state <= st35;
>                 END CASE;
>                 END PROCESS;
>
>                 END fsm;
>
> ---------------------------------------        
> This message was sent using the comp.arch.fpga web interface onhttp://www..FPGARelated.com



Hi,

I recommend you change your BOOLEANs to STD_LOGIC. Also, assuming this
is targeting real hardware, remember that the insertion of coins is
asynchronous and this is a synchronous design. You'll need some logic
for metastability and to create a one clock-wide pulse to your state
machine.

You can do something like this for a testbench:

=====================

library ieee;
use ieee.std_logic_1164.all;

-- Add your library and packages declaration here ...

entity vending_machine_tb is
end vending_machine_tb;

architecture TB_ARCHITECTURE of vending_machine_tb is
-- Component declaration of the tested unit
component vending_machine
port
(
clk : in std_logic;
rst : in std_logic;
nickel_in : in std_logic;
dime_in : in std_logic;
quarter_in : in std_logic;
candy_out : out std_logic;
nickel_out : out std_logic;
dime_out : out std_logic;
quarter_out : out std_logic
);
end component;

-- Stimulus signals - signals mapped to the input and inout ports of
tested entity
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal nickel_in : std_logic := '0';
signal dime_in : std_logic := '0';
signal quarter_in : std_logic := '0';
-- Observed signals - signals mapped to the output ports of tested
entity
signal candy_out : std_logic;
signal nickel_out : std_logic;
signal dime_out : std_logic;
signal quarter_out : std_logic;

-- Add your code here ...

begin

-- Unit Under Test port map
UUT : vending_machine
port map
(
clk => clk,
rst => rst,
nickel_in => nickel_in,
dime_in => dime_in,
quarter_in => quarter_in,
candy_out => candy_out,
nickel_out => nickel_out,
dime_out => dime_out,
quarter_out => quarter_out
);

-- Add your stimulus here ...
clk <= not clk after 50ns;

Stimulus: process

begin

wait for 200 ns;

rst <='1';

wait for 200 ns;

rst <='0';

wait for 200 ns;

nickel_in <='1';

wait for 1 us;

nickel_in <='0';

wait for 1 us;

dime_in <='1';

wait for 1 us;

dime_in <='0';

wait for 1 us;

quarter_in <='1';

wait for 1 us;

quarter_in <='0';

-- add more...

wait;

end process;

end TB_ARCHITECTURE;

configuration TESTBENCH_FOR_vending_machine of vending_machine_tb is
for TB_ARCHITECTURE
for UUT : vending_machine
use entity work.vending_machine(fsm);
end for;
end for;
end TESTBENCH_FOR_vending_machine;

==================

I didn't simulate your design to check its operation. This TB is
simple but it will get you started.

KMS
From: Gabor on
On Jan 16, 12:59 pm, KMS <kms34...(a)gmail.com> wrote:
> Hi,
>
> I recommend you change your BOOLEANs to STD_LOGIC.

If you change the booleans to std_logic, you'll need
to change all the if statements to have a comparison
operator like
if (nickel_in) then . . .
becomes
if (nickel_in = '1') then . . .

If you're not trying to synthesize this logic, I'm not really
clear why you shouldn't use booleans, but then I would
normally have used Verilog.

On the other hand, if you make the code synthesizable,
you can use the Xilinx webpack to generate a testbench
template automatically. That often saves the headache
of writing the signal declarations, instantiations and
initialization logic.

Regards,
Gabor
From: KJ on
> On Jan 16, 10:23 pm, Gabor <ga...(a)alacron.com> wrote:
> to generate a testbench
> template automatically.  That often saves the headache
> of writing the signal declarations, instantiations and
> initialization logic.
>

I never caught on to how this was ever much of a headache and why it
gets touted by the tool vendors as something important. Copy/paste
the entity that you create to make two copies.

The first copy you add the word 'signal' at the begining of the line
and then delete the 'in', 'out' and 'inout' modes from each line and
'presto' you have the signal definitions for the testbench.

The second copy you edit the 'entity' line to make it an
instantiation, change 'generic' and 'port' to 'generic map' and 'port
map' and then use a macro to change all of the lines of the entity
from this...

xyz: in std_logic;

....to this...

xyz => xyz,

Touch it up a bit if you want and you're done...depends on your
preferred editor, but it never takes more than a minute or so.

Not much of a time saver in my opinion. Now something to generate the
actual stimulus and generate the assertion checking would be nice and
would be a real timesaver...

KJ
From: Gabor on
On Jan 17, 1:28 pm, KJ <kkjenni...(a)sbcglobal.net> wrote:
> > On Jan 16, 10:23 pm, Gabor <ga...(a)alacron.com> wrote:
> > to generate a testbench
> > template automatically.  That often saves the headache
> > of writing the signal declarations, instantiations and
> > initialization logic.
>
> I never caught on to how this was ever much of a headache and why it
> gets touted by the tool vendors as something important.  Copy/paste
> the entity that you create to make two copies.
>
> The first copy you add the word 'signal' at the begining of the line
> and then delete the 'in', 'out' and 'inout' modes from each line and
> 'presto' you have the signal definitions for the testbench.
>
> The second copy you edit the 'entity' line to make it an
> instantiation, change 'generic' and 'port' to 'generic map' and 'port
> map' and then use a macro to change all of the lines of the entity
> from this...
>
>    xyz:  in std_logic;
>
> ...to this...
>
>    xyz => xyz,
>
> Touch it up a bit if you want and you're done...depends on your
> preferred editor, but it never takes more than a minute or so.
>
> Not much of a time saver in my opinion.  Now something to generate the
> actual stimulus and generate the assertion checking would be nice and
> would be a real timesaver...
>
> KJ

Well just your description is significanly longer than the buttons
to generate the testbench in ISE. It's actually more of a
timesaver if you use Verilog, where the instantiation and
wires / regs don't resemble the source code like in VHDL.
It's also great if you wanted to quickly make a Verilog
testbench for your VHDL entity or vice versa. This goes
doubly for a beginner, who may not know the basics
required to start the testbench.

Just my 2 cents,
Gabor
From: rickman on
On Jan 16, 10:23 pm, Gabor <ga...(a)alacron.com> wrote:
> On Jan 16, 12:59 pm, KMS <kms34...(a)gmail.com> wrote:
>
> > Hi,
>
> > I recommend you change your BOOLEANs to STD_LOGIC.
>
> If you change the booleans to std_logic, you'll need
> to change all the if statements to have a comparison
> operator like
> if (nickel_in) then . . .
> becomes
> if (nickel_in = '1') then . . .
>
> If you're not trying to synthesize this logic, I'm not really
> clear why you shouldn't use booleans, but then I would
> normally have used Verilog.

I'll second that. There is nothing about Booleans that are evil. The
two times I will replace a Boolean with a std_logic is when I know
this is a signal that will be important in simulation or when it is at
the top level of a synthesized design. I don't recall the exact issue
having other than std_logic or slv at the top level, but it is not a
big deal to work with that restriction. I replace a Boolean with
std_logic for simulation only because a std_logic signal produces a
wiggly line with levels that are easy to see while a Boolean has a
state which must be read in the waveform viewer which can be difficult
with small text. I like Booleans because they can be less typing when
used in an IF statement or in the result of a comparison. In the end,
it more a matter of preference than anything. If you like the format
of your code using Booleans, go ahead. There are no real roadblocks
to using them.

> On the other hand, if you make the code synthesizable,
> you can use the Xilinx webpack to generate a testbench
> template automatically. That often saves the headache
> of writing the signal declarations, instantiations and
> initialization logic.

I'll second that as well. But the template is only the signal
declarations and the component instantiations. You still have to
write the code to drive all the inputs to the UUT. Once you go a
couple of simple test benches you will see how easy they are. When
you need to test more complex code, you will find that your test bench
needs to get a little more complex, but the same concepts apply. The
main thing is to keep it simple and look at other coder's test benches
to get ideas. There are a lot of good designers out there and it is
always good to learn what you can from them. But don't be afraid to
think for yourself too.

Rick