1
\$\begingroup\$

I'm using GHDL. After various update of this thread, under advice, I try to do the simpliest configuration of a testbench with only clock signal. The code compiles correctly, but when I run it (command: ghdl -r entity_name) it stucks. Here is the code:

library ieee;

use ieee.std_logic_1164.all;

 --  A testbench has no ports.
 entity clock is
 generic (   
            clk_period : time := 2 ns -- per le tempistiche
        ); 
 end clock;



architecture clock_0 of clock is    

signal clock : std_logic := '0' ;

 begin



-- clock generation

    --process_clock : process


            --begin


            clock<=NOT clock after clk_period/2;


        --  end process;



        end clock_0;
\$\endgroup\$
7
  • \$\begingroup\$ So.. it sets clock to 0 for half cycle, then to 1 to half cycle. This is what clock cycle looks like, usually.. And what sensitivity list has to do with process running periodically (it is always running periodically..)? \$\endgroup\$
    – Eugene Sh.
    Dec 10, 2015 at 16:15
  • 1
    \$\begingroup\$ if you have no sensitivity list, it will run in a infinit loop \$\endgroup\$
    – Botnic
    Dec 10, 2015 at 16:16
  • \$\begingroup\$ maybe I have misunderstood the meaning of process? I thought process goes inside its code when one of the signals of the sensitivity list change his value. Then, inside the process, the instruction is sequencial. But with this point of view, without a sensitivity list the code inside process shouldn't be runned never...or at least only one time. \$\endgroup\$
    – Daniele
    Dec 10, 2015 at 16:21
  • 2
    \$\begingroup\$ process and process() is not the same ;-) \$\endgroup\$
    – Botnic
    Dec 10, 2015 at 16:29
  • \$\begingroup\$ oh that's Tricky! Thank you for explanation, now I will go to see how process works. \$\endgroup\$
    – Daniele
    Dec 10, 2015 at 16:30

2 Answers 2

2
\$\begingroup\$

First, note that all processes run concurrently with one another. So to have a clock driving your other processes, you want its code in its own process. The code inside the process runs sequentially, and this is how you are able to generate a clock signal with a specific period (using 'wait' statements). A process with a sensitivity list will run whenever one of these signals changes. However, a process with no sensitivity list will always be running. It is up to you to decide when it runs. This is where 'wait' statements come in handy. As a side note, you can't use 'wait' statements in a process with a sensitivity list.

You can implement a simple flip-flop by using either of the two codes below.

process (clk) is
begin
    if clk = '1' then
        Q<=D;
    end if;
end process;


process is
begin
    wait until clk = '1' and clk'event;
    Q<=D;
end process;

Notice how in one design, the process only initiates when there is an event on clk, where it then checks the level. The second process runs continuously, but it waits for an event and level high.

Now, these processes are dependent on the clock. To simulate a clock, we only want the clock to be dependent on time. After half the period we want to toggle the level. So you have a process with no sensitivity list, and the wait statements wait for a certain amount of time before changing the level of the clock.

Hope that helps!

Note: The syntax might be slightly off on those examples, it's been a while since I generated any code..

\$\endgroup\$
4
  • \$\begingroup\$ yes I well understand the difference with process() and process with your example. Thank you, very usefull. \$\endgroup\$
    – Daniele
    Dec 11, 2015 at 8:11
  • \$\begingroup\$ However the code of clock generation doesn't work for me. I'm using GHDL, if I write a process for the generation of clock, when I run it the cmd line is stucked. I think it is because the loop of the clock generation is infinite. Any suggestion? \$\endgroup\$
    – Daniele
    Dec 11, 2015 at 9:12
  • \$\begingroup\$ Hm. Try a concurrent clock generation. \$\endgroup\$
    – Andrew
    Dec 11, 2015 at 15:22
  • \$\begingroup\$ Clk <= not clock after clk_period/2 \$\endgroup\$
    – Andrew
    Dec 11, 2015 at 15:23
1
\$\begingroup\$

For concurrent clock generation, don't forget to initialize clock (it is missing in your code and it will not work without it).

signal clock : std_logic := '0' ;

clock<=NOT clock AFTER clk_period/2;

Why does it work? All concurrent assignments can be converted to an equivalent process by extracting all signals on the right hand side (and select expression) and adding them to a process sensitivity list. Hence, your above code becomes:

process(clock)
begin
  clock<=NOT clock AFTER clk_period/2;
end process ;

Going further, all processes run in their entirety during initialization (delta cycle 0 execute phase). Hence, this process projects clock to change to 1 after half of the clock period. When the new value is placed on clock, the process runs again and schedules the opposite value a half clock period later. One each change of clock, the process (pun intended) repeats.

For your process based clock:

clk_process : process
   begin
        clk <= '0';
        wait for clk_period/2;  --for 0.5 ns signal is '0'.
        clk <= '1';
        wait for clk_period/2;  --for next 0.5 ns signal is '1'.
   end process;

Wait is simply a means of process execution control. The process runs up to a wait statement, suspends until the wait statement says wake up and then resumes. When it reaches the bottom, it simply resumes at the top of the process until it reaches the next wait statement.

To help you understand why this loops, consider the following process:

process(Sel, A, B) 
begin
  case Sel is 
    when '0' => Y <= A ; 
    when '1' => Y <= B ; 
    when others => Y <= (others => 'X') ; 
  end case ; 
end process ; 

The way the language executes this can be described by the following process with a wait statement. The wait on is at the end of the process because during initialization the process with a sensitivity list runs once.

process 
begin
  case Sel is 
    when '0' => Y <= A ; 
    when '1' => Y <= B ; 
    when others => Y <= (others => 'X') ; 
  end case ; 
  wait on Sel, A, B ; 
end process ; 

Hence, all processes naturally loop. To prevent the looping you need a wait statement similar to what you did in data_process.

While your data_process may be correct, I recommend improving readability by using a loop rather than the looping nature of a process:

data_process : process
    variable timedata : time;
begin
  for i in 1 to 100 loop 
    timedata := i*clk_period;
    data <= not data;
    wait for timedata;
    data <= not data;
    -- just added the following wait. 
    -- With out it, the previous assignment to data is meaningless.
    wait for timedata;  
  end loop ;

  std.env.stop ;  -- stop the testbench
  wait ; 
end process;
\$\endgroup\$
8
  • \$\begingroup\$ but why the code that you wrote for clock don't work for me? When I run it, loop indefinitely. Both code, concurrent and inside a process, don't work, even if I initialize the clock. This is really strange. I'm using GHDL, when I write the comando "ghdl -r latch_tb" the prompt stucks. However, for the last advice, I read that the statement "wait" can't be used inside a for, and for this reason I use the if statement. \$\endgroup\$
    – Daniele
    Dec 15, 2015 at 8:25
  • \$\begingroup\$ perhaps I understand the problem...I think is a problem of GHDL. If I embed the clock in a process, and after a certain amount of time (in my case, 100 cycle inside a for) I put a wait (so infinite wait), it works. But, strange thing, doesn't work with " after" statesment, but only with "wait for" statement. However, I thinkg GHDL can't handle the "infinite lenght" signal. \$\endgroup\$
    – Daniele
    Dec 15, 2015 at 13:31
  • \$\begingroup\$ @Daniele For the concurrent clock, initialize it in the signal declaration and it will be fine. Slow down. Simulate and debug small examples. Get them working before moving on to bigger things. Hence, test your clock first. Then add your waveform generation. Then add your design under test. \$\endgroup\$
    – Jim Lewis
    Dec 15, 2015 at 18:44
  • \$\begingroup\$ @Daniele I doubt the issue is GHDL. \$\endgroup\$
    – Jim Lewis
    Dec 15, 2015 at 21:28
  • \$\begingroup\$ @Daniele Your concern about wait and for loops is not a language issue, hence, your testbench can indeed use it as I showed. Sounds like a potentially incorrect RTL rule. \$\endgroup\$
    – Jim Lewis
    Dec 15, 2015 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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