DEADBEEF
DEADBEEF

Reputation: 1

VHDL program's (Design+Testbench) run time is 0 sec

The program contains two source files: 8bit_PU.vhd (entity bit_PU) and 8bit_Tb.vhd. Final version of the program is supposed to read some amount (in this testbench clock frequency is 100Hz) of 3-bit operation codes to operation, decode them, apply it to 8-bit std_logic_vectors operand1 and operand2 (they also change in time) and write the result to 8-bit std_logic_vector result. The code I have now describes only an adding operation, so the operation vector is useless for now.

Here is 8bit_PU.vhd code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity bit_PU is
    port(operation : in std_logic_vector (2 downto 0); 
         Clk       : in std_logic;
         operand1  : in std_logic_vector (7 downto 0); 
         operand2  : in std_logic_vector (7 downto 0); 
         result    : out std_logic_vector(7 downto 0)
         );  
end bit_PU;
 
architecture proc of bit_PU is
        function Add (op1 : std_logic_vector (7 downto 0); 
                      op2 : std_logic_vector (7 downto 0)) return std_logic_vector is
        variable res: std_logic_vector (7 downto 0);  
        begin
            res := std_logic_vector((unsigned(op1)+unsigned(op2)) mod 256);
            return res;
        end function;
 
begin
 
    process(Clk) is
    begin
        if rising_edge(Clk) then
                result <= Add(operand1, operand2);
        end if; 
    end process;
 
end architecture;

Here is 8bit_Tb.vhd code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
   
entity bit_Tb is
end bit_Tb;
   
architecture proc of bit_Tb is
   
        component bit_PU is
            port(operation : in std_logic_vector (2 downto 0);
                 Clk       : in std_logic;
                 operand1  : in std_logic_vector (7 downto 0);
                 operand2  : in std_logic_vector (7 downto 0);
                 result    : out std_logic_vector(7 downto 0)
                 );
        end component bit_PU;
 
signal   Clk  : std_logic  := '0';
constant Freq : integer    := 100;
constant PeriodTime : time := 1000 ms / Freq;
signal   operation  : std_logic_vector (2 downto 0) := "000";
signal   result     : std_logic_vector (7 downto 0);
signal   operand1   : std_logic_vector (7 downto 0) := (others => '0');
signal   operand2   : std_logic_vector (7 downto 0) := (others => '0');
begin                                                                                                                                                                                                                                         
   
    i_bit_PU: component bit_PU
    port map(Clk => Clk,
     operation => operation,
     operand1  => operand1,
     operand2  => operand2,
     result    => result);
   
    Clk <= not Clk after PeriodTime / 2;
   
    process (Clk) is
    begin
        if rising_edge(Clk) then
            if unsigned(operand1) < unsigned(operand2) or (operand1 = x"FF" and operand2 = x"00") then
                operand1 <= std_logic_vector((unsigned(operand1)+1) mod 256);
            else
                operand2 <= std_logic_vector((unsigned(operand2)+1) mod 256);
            end if; 
        end if; 
end process;
   
end architecture;

Analysis and compilation process:

$ ghdl -s 8bit_PU.vhd
$ ghdl -s 8bit_Tb.vhd
$ ghdl -a 8bit_PU.vhd
$ ghdl -a 8bit_Tb.vhd
$ ghdl -e bit_PU
$ ghdl -r bit_PU --vcd=2nd_circuit.vcd

Execution:

$ gtkwave 2nd_circuit.vcd

GTKWave Analyzer v3.3.118 (w)1999-2023 BSI

[0] start time.
[0] end time.

As you can see, program has 0 sec runtime.

I tested both files separately (testbench simulation in 8bit_PU.vhd file; testbench run only) and they worked correctly, so I suppose, that there is some problem in the way I import PU's ports in the testbench. Then I tried to import PU's ports using work library:

---
architecture proc of bit_Tb is
 signal   Clk  : std_logic  := '0';
 constant Freq : integer    := 100;
 constant PeriodTime : time := 1000 ms / Freq;
 signal   operation  : std_logic_vector (2 downto 0) := "000";
 signal   result     : std_logic_vector (7 downto 0);
 signal   operand1   : std_logic_vector (7 downto 0) := (others => '0');
 signal   operand2   : std_logic_vector (7 downto 0) := (others => '0');
 begin
     
      i_bit_PU: entity work.bit_PU(proc) --here
      port map(Clk => Clk,
       operation => operation,
       operand1  => operand1,
       operand2  => operand2,
       result    => result);
---

But, that also didn't help.

Upvotes: 0

Views: 92

Answers (1)

Jim Lewis
Jim Lewis

Reputation: 3983

Your testbench process currently is generating waveforms forever. You would be better served by a test case generator that is more algorithmic. Such as:

    process 
    begin
      for i in 1 to 512 loop 
        if i mod 2 = 1 then 
          operand2 <= std_logic_vector((unsigned(operand2)+1) mod 256);
        else 
          operand1 <= std_logic_vector((unsigned(operand1)+1) mod 256);
        end if ; 
        wait until rising_edge(clk) ; 
     end loop ;

     -- stop your test case
     std.env.stop ; 
   end process ; 

If you did this, you would not need the --stoptime with GHDL as it would simply run until it hit the stop.

In your testbenches, if you are doing math on std_logic_vector, I recommend that you use numeric_std_unsigned instead of all the type conversion gymnastics. Also as @user16145658 mentioned, you don't need the mod 256 as numeric_std family of packages results are always the same size as the largest argument. This will reduce your code to:

    process 
    begin
      for i in 1 to 512 loop 
        if i mod 2 = 1 then 
          operand2 <= operand2 + 1;
        else 
          operand1 <= operand1 + 1 ;
        end if ; 
        wait until rising_edge(clk) ; 
     end loop ;

     -- stop your test case
     std.env.stop ; -- VHDL-2008, so be sure to enable it.
   end process ; 

This sort of thinking will get you started toward thinking about how to write test cases.

Upvotes: 0

Related Questions