[SOLVED] How to introduce delays and understand them in the testbench

Status
Not open for further replies.

bitprolix

Junior Member level 2
Joined
Sep 19, 2013
Messages
24
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
235
Hello everyone,

After some pointers from some expert from this forum for my up-down VHDL counter, I was able to successfully design such a counter. For testing my design, I was given a test bench. My design looks fine, and after looking at the timing diagram, I can see that there is a 2 clock tick delay in my counter, but I'm not able to figure out what is the exact instruction in the testbench, that is causing that delay. I see there are couple of "wait" instruction below. Without understanding properly, what is causing that delay, I started changing some wait instructions below, and started getting more weird waveforms. This is indeed incorrect way to understand what's going on here. Therefore, Can someone please throw some light here. If you look at the waveform attached below, you'll find a 2clock cycle delay when the counter is counting down. It does the counting at the rising edge and only if the ENABLE bit is set, but, I see that at ~380ns, though the ENABLE bit is set, the counter doesn't start counting, until next clock tick. And because of this it is taking 2 additional clock ticks to count from 13 to 5. Why so? For reference purpose, I've put my design, the testbech code, and the resulting waveform below.

1: The counter design
Code:
--Counter design
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

--Entity
entity Counter is
	generic ( BIT_WIDTH   : positive );
	port (
		CLK                 : in bit;
		RESET, ENABLE       : in std_logic;
		STARTADR, STOPADR   : in unsigned ( BIT_WIDTH - 1 downto 0 );
		ADDRESS             : out unsigned ( BIT_WIDTH - 1 downto 0) );
end Counter;

--Register-tranfer level
architecture RTL of Counter is
signal counter : unsigned ( BIT_WIDTH -1 downto 0 );
begin

Cnt: process(CLK, RESET) 
begin
	if ( RESET = '1' ) then 
		counter <= STARTADR;
	elsif (CLK='1' and CLK'event ) then
		if ( ENABLE = '1' ) and ( counter < STOPADR ) then 
			counter <= counter + 1;
		elsif ( ENABLE = '1' ) and ( counter > STOPADR ) then
			counter <= counter - 1;
		end if;
	end if;
end process Cnt;
-- A signal assignment doesn't happen immediately, unlike variable 
-- assignment. It happens at some later time.
ADDRESS <= counter;

end RTL;

2: The testbench (not written by me)
Code:
--Counter testbench
entity CounterTestBench is
end CounterTestBench;

--Content of the environment
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

architecture  Bench  of  CounterTestBench  is

  constant BW             : integer := 4; 
  signal Clk              : bit := '0';
  signal Rst, Ena         : std_logic := '0';
  signal Strt, Stp, Addr  : unsigned ( BW - 1 downto 0 ) := ( others => '0' );
  signal Halt             : boolean := false;

  --Unit Under Test (UUT)
  component Counter
    generic ( BIT_WIDTH : positive );
    port (
      CLK             : in bit;
      RESET, ENABLE     : in std_logic;
      STARTADR, STOPADR : in unsigned ( BIT_WIDTH - 1 downto 0 );
      ADDRESS           : out unsigned ( BIT_WIDTH - 1 downto 0 ) );
  end component;

begin

--UUT
UUT: Counter generic map (BW) port map ( Clk, Rst, Ena, Strt, Stp, Addr );

--Clock generator
Clk <= not Clk after 10 ns when not Halt else unaffected;

--Test sequence
Test_sequence:  process

    procedure MakeSequence
      ( constant START_VALUE, STOP_VALUE, CYCLES_COUNT : positive ) is
    begin
      wait on Clk until Clk = '1';
      Strt <= conv_unsigned ( START_VALUE, BW ) after 1 ns;
      Stp <= conv_unsigned ( STOP_VALUE, BW ) after 1 ns;
      Rst <= '1' after 1 ns;
      Ena <= '0' after 1 ns;
      wait on Clk until Clk = '1';
      Rst <= '0' after 1 ns;
      wait on Clk until Clk = '1';
      Ena <= '1' after 1 ns;
      for i in 0 to CYCLES_COUNT - 4 loop
        wait on Clk until Clk = '1';
      end loop;
      Ena <= '0' after 1 ns;
      wait on Clk until Clk = '1';
    end MakeSequence;

  begin
    MakeSequence ( 2, 12, 16 );  --From 2 to 12, 16 cycles
    MakeSequence ( 13, 5, 16 );  --From 13 down to 5, 16 cycles
    Strt <= ( others  => '0' ) after 1 ns;
    Stp  <= ( others => '0' ) after 1 ns;
    Halt <= true after 50 ns;
    wait;
  end process Test_sequence;

end Bench;

 

You're misinterpreting the waveform. The rising edge of the ENA isn't seen by the CLK as it's transition is 1 ns after the clock edge. Once ENA has gone high the next rising edge of CLK increments/decrements the count.

If you change lines like this wait on Clk until Clk = '1'; to wait on Clk until Clk = '0'; you'll see that the ENA causes the increment/decrement to occur on the correct clock edge.

Regards
 

Thank you so much for your reply.

snip from the diff output, after making the changes:

Code:
--Test sequence							--Test sequence
Test_sequence:  process						Test_sequence:  process

    procedure MakeSequence					    procedure MakeSequence
      ( constant START_VALUE, STOP_VALUE, CYCLES_COUNT : posi	      ( constant START_VALUE, STOP_VALUE, CYCLES_COUNT : posi
    begin							    begin
      wait on Clk until Clk = '1';			      |	      wait on Clk until Clk = '0';
      Strt <= conv_unsigned ( START_VALUE, BW ) after 1 ns;	      Strt <= conv_unsigned ( START_VALUE, BW ) after 1 ns;
      Stp <= conv_unsigned ( STOP_VALUE, BW ) after 1 ns;	      Stp <= conv_unsigned ( STOP_VALUE, BW ) after 1 ns;
      Rst <= '1' after 1 ns;					      Rst <= '1' after 1 ns;
      Ena <= '0' after 1 ns;					      Ena <= '0' after 1 ns;
      wait on Clk until Clk = '1';			      |	      wait on Clk until Clk = '0';
      Rst <= '0' after 1 ns;					      Rst <= '0' after 1 ns;
      wait on Clk until Clk = '1';			      |	      wait on Clk until Clk = '0';
      Ena <= '1' after 1 ns;					      Ena <= '1' after 1 ns;
      for i in 0 to CYCLES_COUNT - 4 loop			      for i in 0 to CYCLES_COUNT - 4 loop
        wait on Clk until Clk = '1';			      |	        wait on Clk until Clk = '0';
      end loop;							      end loop;
      Ena <= '0' after 1 ns;					      Ena <= '0' after 1 ns;
      wait on Clk until Clk = '1';			      |	      wait on Clk until Clk = '0';
    end MakeSequence;						    end MakeSequence;

So, basically I've just replaced all such occurrences of wait on Clk until Clk = '1' to wait on Clk until Clk = '0' in the testbench.
I ran the simulation after the changes which you had suggested, but still i see the delay.(The new waveform is also attached here). I know, I shouldn't be changing the testbench, but just for understanding purpose, I want to get rid of this delay from my design for once. Counting from 12 to 5 happens on every rising edge, but why there is a small gap between 13('1101') to 12('1100'). This is still perplexing to me.

 

The counter doesn't run when ENA is LOW!

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
Cnt: process(CLK, RESET) 
begin
    if ( RESET = '1' ) then 
        counter <= STARTADR;
    elsif (CLK='1' and CLK'event ) then
        if ( ENABLE = '1' ) and ( counter < STOPADR ) then -- ENABLE HAS TO BE '1' TO COUNT UP
            counter <= counter + 1;
        elsif ( ENABLE = '1' ) and ( counter > STOPADR ) then -- ENABLE HAS TO BE '1' TO COUNT DOWN
            counter <= counter - 1;
        end if;
    end if;
end process Cnt;



As soon as there is a rising edge of CLK after ENA is '1' the count changes.

Regards
 
Yes, It was the requirement that, Counter should only count at the rising edge of the clock, provided ENABLE signal is also set, and therefore I designed the counter code like that. I now understood what you meant and the same behaviour is depicted in the timing diagram as well. So let me ask you this in another way, How can i control the ENABLE signal, ie, as per the timing diagram, i see that it remained LOW for 4 clock ticks. How can i change this behaviour?
 

The change would have to be done in the procedure by removing some of the waits for clk edge (notice there are four of them that are not in the loop). You'ld have to adjust the stimulus so you don't cause reset or load problems.

Regards
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…