Search code examples
vhdlsimulation

fatal error in modelsim during simulation


This is my main code in VHDL:

library ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;

  entity pid is
    port( error ,Kp, Ti, Td ,dt: in std_logic_vector(7 downto 0);
      reset : in std_logic;
      output :out std_logic_vector(31 downto 0) );
    end pid;

    architecture pid_arch of pid is
    -------------------------------- functions
    function add_vec(num1,num2,num3: in std_logic_vector(15 downto 0)) return std_logic_vector is
    variable v_TEST_VARIABLE1: integer;
    variable v_TEST_VARIABLE2: integer;
    variable v_TEST_VARIABLE3: integer;
    variable n_times1: integer;
    variable n_times2: integer;
variable sum: integer;    
    begin
        v_TEST_VARIABLE1 := to_integer(unsigned(num1)) ; 
       v_TEST_VARIABLE2 := to_integer(unsigned(num2)) ;
       v_TEST_VARIABLE3 := to_integer(unsigned(num3 )); 

       --for n_times1 in 1 to v_TEST_VARIABLE2 loop
      --   v_TEST_VARIABLE1: = v_TEST_VARIABLE1 + '1';
     --  end loop;
     --  for n_times2 in 1 to v_TEST_VARIABLE3 loop
     --    v_TEST_VARIABLE1:= v_TEST_VARIABLE1 + '1';
      -- end loop;
      sum:= v_TEST_VARIABLE1+ v_TEST_VARIABLE2 + v_TEST_VARIABLE3;
       return std_logic_vector(to_unsigned(sum,32));
     end add_vec;
    -----------------------------------
    function sub(num1, num2: in std_logic_vector(7 downto 0)) return std_logic_vector is
    variable v_TEST_VARIABLE1: integer;
    variable v_TEST_VARIABLE2: integer;
    variable difference: integer;
    begin
       v_TEST_VARIABLE1 := to_integer(unsigned(num1)) ; 
       v_TEST_VARIABLE2 := to_integer(unsigned(num2)) ;
       difference := v_TEST_VARIABLE1 - v_TEST_VARIABLE2;
       return std_logic_vector(to_unsigned(difference,8));
     end sub;
    ------------------------------------
    function mul(num1,num2 : in std_logic_vector(7 DOWNTO 0)) return std_logic_vector is
    variable v_TEST_VARIABLE1 : integer;
    variable v_TEST_VARIABLE2 : integer;
    variable n_times: integer:=1;
    variable product: integer:=0;
    begin 
       v_TEST_VARIABLE1 := to_integer(unsigned(num1)) ; 
       v_TEST_VARIABLE2 := to_integer(unsigned(num2)) ;
      for n_times in 1 to v_TEST_VARIABLE2 loop
        product:=product + v_TEST_VARIABLE1;
      end loop;
    return std_logic_vector(to_unsigned(product,16));
  end mul;
  --------------------------------
    function div(num1, num2 : in std_logic_vector(7 DOWNTO 0)) return std_logic_vector is
             variable v_TEST_VARIABLE1 : integer;
             variable v_TEST_VARIABLE2 : integer;
             variable quotient :integer;
        --           begin 
      --P3: PROCESS(num1, num2)
       variable n_times: integer:=1;
     begin     
        if num1>num2 then
       v_TEST_VARIABLE1 := to_integer(unsigned(num1)) ; 
       v_TEST_VARIABLE2 := to_integer(unsigned(num2)) ;
       L1:loop
         n_times := n_times + 1;
        exit when ((v_TEST_VARIABLE2 -  v_TEST_VARIABLE1)>0);
        v_TEST_VARIABLE1 := v_TEST_VARIABLE1 - v_TEST_VARIABLE2;
       end loop L1;

    quotient := n_times-1;
   elsif num2>num1 then
      v_TEST_VARIABLE1 := to_integer(unsigned(num1)) ;  
       v_TEST_VARIABLE2 := to_integer(unsigned(num2)) ;
       L2:loop
        n_times:=n_times+1;
       exit when ((v_TEST_VARIABLE1 -  v_TEST_VARIABLE2)>0);
       v_TEST_VARIABLE2 := v_TEST_VARIABLE2 - v_TEST_VARIABLE1;

   quotient := n_times-1;

end loop L2;
    else
      quotient := 1;
    end if;
    return std_logic_vector(to_unsigned(quotient,16));
 -- end PROCESS P3;
      end div;

  ---------------------------------
  function derivative(error, previous_error, dt :in std_logic_vector(7 downto 0)) return std_logic_vector is
  variable derivative_val: std_logic_vector(15 downto 0);
  begin
      derivative_val := div(sub(error,previous_error),dt);
      return derivative_val;
  end derivative;
  --------------------------------------------

function integration(error,dt:in std_logic_vector(7 downto 0);current_integration :in std_logic_vector(15 downto 0);reset : in std_logic) return std_logic_vector is
       begin  
         if (reset='1') then
           return "0000000000000000";
      else  
         --current_integration := add_vec(current_integration, mul(error,dt),x"0000");
        -- return current_integration;
        return add_vec(current_integration, mul(error,dt),x"0000");
       end if;
end integration;
    -------------------------
     begin 
        P1:PROCESS (reset ,error , Kp, Ti, Td)
        variable proportional_term : std_logic_vector(15 downto 0):=x"0000";
        variable derivative1: std_logic_vector(15 downto 0) := x"0000";
       variable derivative_term: std_logic_vector(31 downto 0) ; 
       variable integration1: std_logic_vector(15 downto 0) :=x"0000";
       variable integration_term : std_logic_vector(15 downto 0) := x"0000";
       variable current_integration: std_logic_vector(15 downto 0) ;
       variable previous_error: std_logic_vector(7 downto 0) := "00000000";
       variable v1: std_logic_vector( 15 downto 0);
       variable v2 : std_logic_vector( 23 downto 0);
       variable v3 : std_logic_vector (7 downto 0);
       ------------------checked till here

        begin 
        if (reset='1') then
          --  output <= x"00000000";
            previous_error :="00000000";
            current_integration := x"0000";
      else  

         --output <= Kp*(error + integration/Ti + derivative*Td);
         current_integration := integration1;
         end if;
        -- proportional_term := mul(Kp,error);
           proportional_term := std_logic_vector(unsigned(Kp) * unsigned(error));
        -- derivative_term := mul(mul(Kp,Td), derivative(error, previous_error,dt));
        v1 :=std_logic_vector(unsigned(Kp)*unsigned(Td));
        derivative1 := derivative(error, previous_error,dt);
        derivative_term := std_logic_vector(unsigned(v1)*unsigned(derivative1));
        integration1 :=integration(error,dt,current_integration,reset);
        v2 :=std_logic_vector((unsigned(Kp)*unsigned(integration1)));
        v3 := std_logic_vector(resize(unsigned(v2),8));
         integration_term := div( v3, Ti);
               --   integration_term := div(mul(Kp, integration(error,dt,current_integration,reset)) , Ti);
         previous_error :=error;
      output <= add_vec(std_logic_vector(resize(unsigned(proportional_term),16)) , std_logic_vector(resize(unsigned(derivative_term),16)), std_logic_vector(resize(unsigned(integration_term),16)));
        --output <= x"0000";
        --Kp*(error + integration/Ti + derivative*Td);
      END PROCESS P1;
      end pid_arch;

And this is the testbench:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.numeric_std.all;

   ENTITY pid_2_tb IS 
END pid_2_tb;

ARCHITECTURE behavior OF pid_2_tb IS

    COMPONENT pid  --'test' is the name of the module needed to be tested.

    port(error ,Kp, Ti, Td ,dt: in std_logic_vector(7 downto 0);
      reset : in std_logic;
      output :out std_logic_vector(31 downto 0) );

    END COMPONENT;
   signal error : std_logic_vector(7 downto 0) := "00000000";
   signal Kp : std_logic_vector(7 downto 0) := "00001000";
   signal Ti : std_logic_vector(7 downto 0) := "00000001";
   signal Td : std_logic_vector(7 downto 0) := "00000001";
   signal dt : std_logic_vector(7 downto 0) := "00000001";
  signal reset : std_logic := '1';

   signal output : std_logic_vector(31 downto 0);

   constant clk_period : time := 1 ns;
BEGIN
   uut: pid PORT MAP (
         error => error,
          Kp => Kp,
          Ti => Ti,
          Td => Td,
          dt => dt,
          reset => reset,
          output => output
        );       

   clk_process :process
   begin
        error <= "00000001";
        reset <= '1';
        wait for clk_period/2;  
        error <= "00000010";
        reset <= '0';
        wait for clk_period/2;  --for next 0.5 ns signal is '1'.
   end process;
   -- Stimulus process
  stim_proc: process
   begin         

        wait for 17 ns;
        error <= "00000011";
        reset <= '0';
        wait for 1 ns;
        error <= "00000010";
        reset <= '0';
        wait;
  end process;

END;

The two show no error on compilation. I have tried simulating for smaller programs using the same functions, and that worked well. But on simulation it gives Fatal error. What can be the reasons for the same? I am a newbie in vhdl. Please help me out. Thanks in advance.


Solution

  • The div function uses a loop where the exit condition never becomes true, whereby the div function will never return, thus the simulation time will never advance.

    One relevant part of the div code is in:

    elsif num2 > num1 then
      v_TEST_VARIABLE1 := to_integer(unsigned(num1));
      v_TEST_VARIABLE2 := to_integer(unsigned(num2));
      L2 : loop
        n_times          := n_times+1;
        exit when ((v_TEST_VARIABLE1 - v_TEST_VARIABLE2) > 0);
        v_TEST_VARIABLE2 := v_TEST_VARIABLE2 - v_TEST_VARIABLE1;
        quotient := n_times-1;
      end loop L2;
    

    But if num1 is 0 (zero) then v_TEST_VARIABLE2 is never decremented in the loop, thus ((v_TEST_VARIABLE1 - v_TEST_VARIABLE2) > 0) never becomes true.

    The div function must be updated to handle this case also, or arguments must be guaranteed never to result in the case.