Forum Discussion

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

simulate simple traffic light example (VHDL, DE2)

Hi,

i wrote a simple VHDL traffic light program using a clock divider to get a 1hz clock which i think is helpfull.

clockdivider:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- clockdivider ... divides x-hz clock into 1hz clock
entity clockdiv is
	port 
	( 
		-- Input ports
		clock50mhz : in  STD_LOGIC;
		clockReset : in  STD_LOGIC;
		
		-- Output ports
		clockOut : out  STD_LOGIC
	);
end clockdiv;
architecture controller of clockdiv is
	signal count : integer;
	signal clock1hz : STD_LOGIC;
begin
	divide: process(clock50mhz,clockReset)
	begin
		if(clockReset = '1') then
			count <= 0;
			clock1hz <= '0';
		elsif rising_edge(clock50mhz) then
			if (count >= 25000000) then
				clock1hz <=not clock1hz;
				count <= 0;
			else
				count<=count+1;
			end if;
		end if;
	end process;
	clockOut <= clock1hz;
end controller;

traffic light control:

library IEEE; 
use IEEE.STD_LOGIC_1164.all; 
use IEEE.STD_LOGIC_unsigned.all;
entity ampel_basic is
	port
	(
		-- Input ports
		clock1hz			: in 	STD_LOGIC;
		reset				: in 	STD_LOGIC;
		-- Output ports
		tLightsRed1		: out STD_LOGIC;
		tLightsYellow1	: out STD_LOGIC;
		tLightsGreen1	: out STD_LOGIC;
		tLightsRed2		: out STD_LOGIC;
		tLightsYellow2	: out STD_LOGIC;
		tLightsGreen2	: out STD_LOGIC
	);
end ampel_basic;
architecture controller of ampel_basic is
	signal count : integer;
begin
	process(clock1hz, reset)
	begin
		if(reset = '1') then
			count <= 0;			
		elsif rising_edge(clock1hz) then
			
			count <= count +1;
			
			if (count = 1) then -- light 1 green
				tLightsGreen1 	<= '1';
				tLightsYellow1 <= '0';
				tLightsRed1 	<= '0';
				tLightsGreen2 	<= '0';
				tLightsYellow2 <= '0';
				tLightsRed2 	<= '1';
			elsif	(count = 30) then
				tLightsGreen1 	<= '0';
				tLightsYellow1 <= '1';
				tLightsRed1 	<= '0';
				tLightsGreen2 	<= '0';
				tLightsYellow2 <= '0';
				tLightsRed2 	<= '1';
			elsif (count = 31) then -- light 2 green
				tLightsGreen1 	<= '0';
				tLightsYellow1 <= '0';
				tLightsRed1 	<= '1';
				tLightsGreen2 	<= '1';
				tLightsYellow2 <= '0';
				tLightsRed2 	<= '0';	
			elsif (count = 60) then
				tLightsGreen1 	<= '0';
				tLightsYellow1 <= '0';
				tLightsRed1 	<= '1';
				tLightsGreen2 	<= '0';
				tLightsYellow2 <= '1';
				tLightsRed2 	<= '0';			
				
				count <= 0;	-- reset counter
			end if;		
		end if;
	end process;
		
end controller;

i connected both vhdl parts with a root shematic file and mapped the necessary ins and outs according to the DE2 user manual.

First problem -> i'm not sure that my code is working as i expect.

An the second one -> i want to create a waveform simulation to visualise the traffic light behavior

any help would be great!

thx alot

6 Replies

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

    To do both, you will need to create a testbench. A testbench is behavioural code that you do not compile in quartus - you use a simulation tool like modelsim. In it, you instantiate the unit under test (UUT) and drive the inputs and monitor the outputs. You can even read and write to text files if you want.

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

    is there a good tutorial for it, and do you see any major flaws in my code?

    thx for your quick answer
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The only main flaw is not with the code, but the design. Generating clocks in logic is usually fine for ASICs, but not so ok on FPGAs. With a 1MHz output, you'll probably be ok, but its not a good habit to get into. It is best to clock all logic on the same clock and generate different clock enables to get the different frequencies you need. This means that Timequest can easily check all the timings. With logic generated clocks you may have setup and hold time issues.

    Second is a little niggle - std_logic_signed/unsigned/arith are not standard VHDL libraries. The library that is standard is VHDL. Arithmatic was never meant to be done with std_logic_vectors. People keep using these because they were distributed by Synopsis in the early 90s. Numeric_std became part of VHDL in 1993, so engineers keep teaching old methods, along with many text books, and people never get themselves up to date (well, if up to date means using code that was standardised nearly 20 years ago!!!)

    Anyway, rant over.

    For tutorials, you'll probably find plenty if you google "VHDL testbench". But why not have a play around.

    heres an example of what you can do in testbenches - this one generates random numbers and checks for less than or greater than zero on each clock edge, and reports each one to the simulator console:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.math_real.all;
    entity play_TB is
      
    end entity;
      
    architecture rtl of play_TB is
      
      signal reset  : std_logic;
      signal clk    : std_logic := '0';
      
      signal data   : integer;
      signal ENDSIM : boolean;
      
      
      -----------------------------------------------
      --RANDOM INTEGER GENERATORS
      -----------------------------------------------
      procedure rand_int(  variable seed1, seed2 : inout positive; result : out integer) is
        variable rand    : real;
      begin
        uniform(seed1, seed2, rand);   --from the math_real library
        result := integer(((rand - 0.5) *2.0) * real(integer'high));  --makes random range from integer'low to integer'high by making "rand" range -1 to +1
      end procedure;
      
      --------------------------------------------------------------------------------------------------
      --Writes a string to the Simulator Console.
      --------------------------------------------------------------------------------------------------
      procedure echo (arg : in string := "") is
      begin
        std.textio.write(std.textio.output, arg);
      end procedure echo; 
      
    begin
      
      
      reset  <= '1', '0' after 100 ns;
      ENDSIM <= false, true after 1 ms;
      
      process
      begin
        while not ENDSIM loop
          clk <= not clk;
          wait for 10 ns;
        end loop;
        
        wait;
      end process;
      
      process
        variable s1, s2 : positive := 9134924;
        variable r      : integer;
        variable n      : positive;
        
      begin
        wait until reset = '0';
        n := 1;
        
        while not ENDSIM loop
          rand_int(s1, s2, r);
          
          data <= r;
          wait until rising_edge(clk);
          
          echo("output " & integer'image(n) & ": " & integer'image(data) & " ");
          
          if data > 0 then echo("Greater than zero" & LF);
          else             echo("Less than zero" & LF);
          end if;
            
          n := n + 1;
        end loop;
        
        wait;
      end process;
      
    end rtl;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thx again,

    i don't know if a testbench is what i'm looking for. i need some kind of waveform , which shows the output signals + time dependency

    and i'm trying to get an 1hz clock ... will this be possible with my approach?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The waveform will be generated in the simulator, but you still need to generate a clock and reset, and this is where the testbench comes in,

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

    --- Quote Start ---

    The waveform will be generated in the simulator, but you still need to generate a clock and reset, and this is where the testbench comes in,

    --- Quote End ---

    ah okay .. so i can't just simulate the board inputs and the 50 mhz clock, which is hardwired on the altera de2?

    again thx for the quick answer