模拟过程中modelsim的致命错误

时间:2014-06-24 09:15:05

标签: vhdl simulation

这是我在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;

这是测试平台:

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;

这两个在编译时没有显示错误。我尝试使用相同的功能模拟较小的程序,并且效果很好。 但是在模拟上它会给出致命错误。可能是同样的原因是什么? 我是vhdl的新手。请帮帮我。 提前谢谢。

2 个答案:

答案 0 :(得分:1)

您的进程P1在实体pid中不断循环。我想,当一些东西连续旋转时,Modelsim会使用一个保护计时器来引发异常。

我通过分而治之的方式找到了这个:

ghdl -a pid.vhdl # analyze, also contains pid_2_tb entity/architecture ghdl -e pid_2_tb # elaborates ghdl -r pid_2_tb --stop-time=100ns # run the simulation (batch mode) guard time to stop)

永远如此: ghdl -e pid # elaborate just the component ghdl -r pid --stop-time=30ns # run just the component ../../../src/ieee/numeric_std-body.v93:2098:7:@0ms:(assertion warning): NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0 ../../../src/ieee/numeric_std-body.v93:2098:7:@0ms:(assertion warning): NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

(它至少在做某事 - 虽然仍在永远运行)。

因此,要知道您的设计的哪一部分(实体/架构pid)要关注。立即查看过程,发现没有等待或敏感性声明。

在P1中注释掉灵敏度列表,并在第一个函数调用(派生)之前放置一个等待语句。那就完了。

在P1(到div)的下一个函数调用之前移动了wait语句。从未完成。

所以你的衍生功能还没有完成。恐怖的衍生函数包含对div和sub的调用。

查看函数派生中的第一个函数调用(到div),我们发现不是一个而是两个循环无界循环语句:

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;
    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 div;

我不倾向于独立测试你的算法(例如在C中或使用报告语句),但我猜测v_test_variable1和v_test_variable2之间的区别在两个循环中的一个中没有变为正,或其中一个应该比较小于而不是大于。另一种可能性是你将某些东西归零。

您的代码也不具备合成资格。你没有无限的循环。循环在综合中展开,并且需要具有静态迭代次数。

当然,你可能会在其他地方遇到其他问题。

答案 1 :(得分:0)

div函数使用loop exit条件永远不会变为真, 因此div函数将永远不会返回,因此模拟时间将会返回 永远不会前进。

div代码的一个相关部分位于:

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;

但如果num1为0(零),那么v_TEST_VARIABLE2永远不会递减 循环,因此((v_TEST_VARIABLE1 - v_TEST_VARIABLE2) > 0)永远不会成真。

必须更新div函数以处理这种情况,或参数必须 保证永远不会导致这种情况。