1
\$\begingroup\$

I am trying to test out a module I made in VHDL using Vivado. I am having some issues with my test bench though, as in I don't even see the clock signal changing.

The snippet of code below shows me constantly changing the clock, as well as driving some signals with certain values at specific times. I simplified it so that I am not even testing the component I made. I am simply setting the signals to certain values at certain times.

library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;

entity pwmTB is
end entity pwmTB;

architecture behav of pwmTB is

signal reset_t : std_logic;
signal clk_t : std_logic;
signal led_mode_t : std_logic_vector(15 downto 0);
signal led_breathing_t : std_logic_vector(15 downto 0);
signal led_max_t : std_logic_vector(15 downto 0);
signal led_min_t : std_logic_vector(15 downto 0);
signal pwm_out_t : std_logic;

begin
    clk_t <= '0';
    --24MHz clock -> 50ns period
    clk_t <= not clk_t after 25ns;
    
    test_led_off : process
    begin
       clk_t <= '0';
       wait for 10 ps;
       led_mode_t <= X"0000";
       led_breathing_t <= X"F000";
       led_max_t <= X"0100";
       led_min_t <= X"0010";
       wait for 5000ms;
    end process test_led_off;
end architecture behav;

and the simulation output:

enter image description here

I do notice the signals change from 'UUUU' to 'XXXX' at 10ps, which sort of correlates to my wait for 10 ps, but none of the values I drive the signals with appear. And the clock doesn't display at all. At one point yesterday, the clk_t <= not clk_t after 25ns was displaying the clock output, and I haven't been able to get it display again since.

Why aren't these signals that I am directly driving not displaying anything? Is it a certain setting in Vivado? I have been reading the documentation but still haven't found anything.

\$\endgroup\$
0

2 Answers 2

0
\$\begingroup\$

Separate your code into different process blocks. The clock signal should be in a different block from the others:

begin
  ClockGen: process
  begin
    for i in 0 to 15 loop
      clk_t <= '0';
      wait for 25 NS;
      clk_t <= '1';
      wait for 25 NS;
    end loop;
    wait;
  end process ClockGen;
    
    test_led_off : process
    begin
       wait for 10 ps;
       led_mode_t <= X"0000";
       led_breathing_t <= X"F000";
       led_max_t <= X"0100";
       led_min_t <= X"0010";
       wait for 500 ns;
       stop;
    end process test_led_off;
end architecture behav;

Runnable example on EDA playground

Click to show waveforms

\$\endgroup\$
3
  • \$\begingroup\$ Thanks! I am seeing some outputs now. I just edited my post, there was a small typo. I originally had all these separate processes like you suggested for setting certain signals, with the clock signal being outside of a process. If everything needs to be in a process block, then I understand why the clock output wasn't displaying, but why weren't the signals I set displaying? \$\endgroup\$ Commented Jul 31 at 17:31
  • \$\begingroup\$ I understand now... I think I was running all my processes at the same exact time, so the values all became undefined. Thanks! \$\endgroup\$ Commented Jul 31 at 18:01
  • \$\begingroup\$ @jukebox41188: You're welcome. Feel free to vote/accept. \$\endgroup\$
    – toolic
    Commented Jul 31 at 19:31
0
\$\begingroup\$

Your pwmTB code shows three drivers for clk_t.

Each concurrent signal assignment statement represents an equivalent process with sequential signal assignment. Each process asssigning a signal has a driver for that signal. A resolved data type (e.g. std_logic) has a value that results from the value of each of it's drivers being applied to a resolution function specificed in the resolved type's delaration. Here that's found in package std_logic_1164 in library ieee.

The intial value can be applied in the declaration of clk_t instead of the mistaken view that driver values are applied sequentially (and somehow released).

The assignment of '0' to clk_t is the explicit process statement can be replaced with an assignment to a signal used to communicate to the clock process generating the clock (the middle concurrent assignment statement.

if you really want to stop the clock in your testbench's test_led_off process you can use a signal:

library ieee;
use ieee.std_logic_1164.all;
-- use IEEE.numeric_std.all;        -- These two packages declarations aren't
-- use IEEE.std_logic_unsigned.all; -- used here.

entity pwmTB is
end entity;

architecture clock_stops of pwmTB is
    signal reset_t : std_logic;
    signal clk_t : std_logic := '0';  -- CHANGED ADDED initial value
    signal led_mode_t : std_logic_vector(15 downto 0);
    signal led_breathing_t : std_logic_vector(15 downto 0);
    signal led_max_t : std_logic_vector(15 downto 0);
    signal led_min_t : std_logic_vector(15 downto 0);
    signal pwm_out_t : std_logic;
    signal stopped:     boolean; -- defaults to FALSE, CHANGED, ADDED
begin
    -- clk_t <= '0'; -- CHANGED - elliminate multiple drivrs
                       -- prefix)
    --24MHz clock -> 50ns period  -- NOTE the period for 20MHz is 50 nanno secs

    clk_t <= not clk_t after 25 ns when not stopped;   -- CHANGED WAS 25ns
    
    test_led_off : process
    begin
        wait for 100 ns;  -- CHANGED ADDED to shown the clock runs
       -- clk_t <= '0';  -- CHANGED - eleminate multiple drivers
       stopped <= TRUE; 
       wait for 10 ps;   
       led_mode_t <= X"0000";
       led_breathing_t <= X"F000";
       led_max_t <= X"0100";
       led_min_t <= X"0010";
       wait for 5000 ms;  -- CHANGED was 5000ms
       wait;              -- stop simulation,odtherwise test_led_off will repeat
    end process test_led_off;
end architecture;

This produces:

pwmtb waveform

Processes communicate with signals. The value of a particular driver can't readily detected programmatically in a VHDL model. In a secondary design unit (architecture) or block statement we see the resolved value of the net comprised of all active drivers and any mode in or mode inout ports and any mode out, mode inout and mode buffer ports of any component instantiations on the net.

A synthesis tool for most FPGA families will detected multiple drivers for the portion of your code submitted to it. Multiple drivers are legal in VHDL otherwise, used for single ended drivers and tristated signals for instance. Some FPGA families synthesis tools can infer multiplexers for multiple drivers with all but one driving 'Z' for instance.

Your code has had the required separator between an abstract literal and adjacent identifier added for portability. The simulation was performed with ghdl and the waveform displayed with gtkwave. ghdl requires the standard mandated separator. There can be cases in -2008 where physical literals can be mistaken for bit strings with a length specifier which would be a lexical element while a physical literal is a syntactic target. A VHDL lexical analyzer is not required to identify character strings of length 1 and otherwise only recognizes reserved words.

This question might be found to be a duplicate since the problem is multiple drivers. It's almost guaranteed it would have been detected as a duplicate on Stackoverflow.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.