亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

掌握VHDL函数:高效设计实战指南

函数是VHDL中的子程序,用于实现常用算法。函数接受零个或多个输入值,且总是返回一个值。除了返回值,函数与过程的区别在于不能包含Wait语句,意味着函数始终消耗零仿真时间。

若你熟悉其他语言的函数或方法,VHDL函数应易于掌握。VHDL中不能省略返回值或返回void,函数必须返回某值且返回值必须赋给某物。

本文属基础VHDL教程系列。

VHDL有两类函数:纯和不纯函数。纯函数不允许修改或读取任何外部信号。调用纯函数时给定特定参数,确定返回相同值。我们说该函数无副作用。

VHDL声明函数的语法:

[pure|impure] function <function_name> (<parameter1_name> : <parameter1_type> := <default_value>;                                          <parameter2_name> : <parameter2_type> := <default_value>;                                         ... ) return <return_type> is     <constant_or_variable_declaration> begin     <code_performed_by_the_function>     return <value> end function;

pure/impure关键字可选,省略默认为pure。所有参数在函数内视为常量,不可更改。默认值可选,函数必须在return语句终止。

函数在is和begin间有自己的声明区。此处声明的常量、信号或变量仅在函数内有效,后续调用不保留值。

练习

本教程聚焦纯函数,不纯函数将在系列后续教程讲解。

上一教程用有限状态机(FSM)创建了红绿灯控制器模块。我们从一个状态复制粘贴许多计时器计算行到另一状态,仅微调一个常量。

找出如何用函数简化状态机代码:

函数测试平台最终代码:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T21_FunctionTb is end entity; architecture sim of T21_FunctionTb is -- We are using a low clock frequency to speed up the simulation constant ClockFrequencyHz : integer := 100; -- 100 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal NorthRed : std_logic; signal NorthYellow : std_logic; signal NorthGreen : std_logic; signal WestRed : std_logic; signal WestYellow : std_logic; signal WestGreen : std_logic; begin -- The Device Under Test (DUT) i_TrafficLights : entity work.T21_TrafficLights(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, NorthRed => NorthRed, NorthYellow => NorthYellow, NorthGreen => NorthGreen, WestRed => WestRed, WestYellow => WestYellow, WestGreen => WestGreen); -- Process for generating clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Take the DUT out of reset nRst <= '1'; wait; end process; end architecture; 

红绿灯模块最终代码:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T21_TrafficLights is generic(ClockFrequencyHz : natural); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset NorthRed : out std_logic; NorthYellow : out std_logic; NorthGreen : out std_logic; WestRed : out std_logic; WestYellow : out std_logic; WestGreen : out std_logic); end entity; architecture rtl of T21_TrafficLights is -- Enumerated type declaration and state signal declaration type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; -- Calculate the number of clock cycles in minutes/seconds function CounterVal(Minutes : integer := 0; Seconds : integer := 0) return integer is variable TotalSeconds : integer; begin TotalSeconds := Seconds + Minutes * 60; return TotalSeconds * ClockFrequencyHz -1; end function; -- Counter for counting clock periods, 1 minute max signal Counter : integer range 0 to CounterVal(Minutes => 1) +1; begin process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then -- Reset values NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; State <= NorthNext; Counter <= 0; else -- Default values NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is -- Red light in all directions when NorthNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= StartNorth; end if; -- Yellow light in north/south directions when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= North; end if; -- Green light in north/south directions when North => NorthGreen <= '1'; WestRed <= '1'; -- If 1 minute has passed if Counter = CounterVal(Minutes => 1) then Counter <= 0; State <= StopNorth; end if; -- Red and yellow light in north/south direction when StopNorth => NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= WestNext; end if; -- Red light in all directions when WestNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passedf if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= StartWest; end if; -- Yellow light in west/east direction when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= West; end if; -- Green light in west/east direction when West => NorthRed <= '1'; WestGreen <= '1'; -- If 1 minute has passed if Counter = CounterVal(Minutes => 1) then Counter <= 0; State <= StopWest; end if; -- Red and yellow light in west/east direction when StopWest => NorthRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = CounterVal(Seconds => 5) then Counter <= 0; State <= NorthNext; end if; end case; end if; end if; end process; end architecture; 

在ModelSim控制台输入run 5 min命令后的波形:
掌握VHDL函数:高效设计实战指南

在StartNorth状态转入/转出处加光标的波形:
掌握VHDL函数:高效设计实战指南

分析

我们用新建CounterVal函数调用替换了上一教程if Counter = ClockFrequencyHz * 5 -1 then的计时器计算:if Counter = CounterVal(Seconds => 5) then。

从第一张波形截图可见模块功能未变。用函数处理重复任务是良好设计实践。特别是能用包含Minutes和Seconds等术语的可读行替换计算。

使用函数另一优势是可一次性修改所有计时器实现,而非逐行修改。例如若CounterVal函数写return TotalSeconds * ClockFrequencyHz;,所有计时器会多一个时钟周期。可在CounterVal函数改为return TotalSeconds * ClockFrequencyHz -1;,一次性修复所有计时器。

观察最后波形截图,可见为何需从CounterVal返回的计时器值减1。此波形考察StartNorth状态持续时间,应恰好5秒。State信号变为StartNorth时Counter值为0,仅在下一时钟周期变化。若计数到500周期,StartNorth实际持续501周期。测试平台100Hz下500周期正好5秒。

掌握VHDL函数:高效设计实战指南

要点

进入下一教程 »


VHDL

  1. 刀具磨床实战技法指南:从入门到精通
  2. 钼如何塑造现代工业:用途、优势与供应动态
  3. C 语言 realloc() 完全指南:语法、最佳实践与实战案例
  4. C 语言 free() 函数实战指南:正确释放动态内存、防泄漏与避坑全解析
  5. VHDL 字符串列表创建:最佳实践与示例
  6. 优雅结束 VHDL 测试平台仿真
  7. VHDL 实现 PWM 控制器:设计、仿真与 FPGA 演示
  8. VHDL 生成随机数:从均匀分布到 OSVVM
  9. 利用进程内过程简化VHDL状态机设计
  10. 使用VHDL不纯函数提升FSM可读性与可维护性
  11. 用VHDL设计有限状态机:红绿灯实战范例
  12. 在VHDL中使用过程:用可复用代码简化设计