这是我在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的新手。请帮帮我。 提前谢谢。
答案 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
函数以处理这种情况,或参数必须
保证永远不会导致这种情况。