VHDL子程序:并发过程调用、函数与重载详解
立即解锁
发布时间: 2025-08-16 01:28:46 阅读量: 5 订阅数: 11 


VHDL设计指南:从入门到精通
### VHDL 子程序:并发过程调用、函数与重载详解
#### 1. 并发过程调用语句
在 VHDL 中,过程调用可以以并发的方式进行。并发过程调用语句是一种简写形式,它等价于一个包含顺序过程调用语句的进程。
##### 1.1 参数关联方式
过程调用时,参数可以采用位置关联或命名关联的方式。例如,有如下过程声明:
```vhdl
procedure p ( f1 : in t1; f2 : in t2;
f3 : out t3; f4 : in t4 := v4 ) is
begin
...
end procedure p;
```
可以通过以下几种方式调用该过程:
- `p ( val1, val2, var3, val4 );` (位置关联)
- `p ( f1 => val1, f2 => val2, f4 => val4, f3 => var3 );` (命名关联)
- `p ( val1, val2, f4 => open, f3 => var3 );` (混合关联)
- `p ( val1, val2, var3 );` (位置关联,使用默认值)
##### 1.2 并发过程调用语法
并发过程调用语句的语法规则如下:
```plaintext
concurrent_procedure_call_statement ⇐
[ label : ] procedure_name [ ( parameter_association_list ) ] ;
```
它看起来与普通的顺序过程调用相同,但区别在于它是作为并发语句出现的。例如:
```vhdl
call_proc : p ( s1, s2, val1 );
```
等价于以下进程:
```vhdl
call_proc : process is
begin
p ( s1, s2, val1 );
wait on s1, s2;
end process call_proc;
```
等价进程中包含一个等待语句,其敏感列表包含实际参数列表中提到的信号。只有与输入模式或输入输出模式参数关联的信号才会包含在敏感列表中。
##### 1.3 示例:检查建立时间的过程
下面是一个检查数据信号相对于时钟信号建立时间的过程:
```vhdl
procedure check_setup ( signal data, clock : in bit;
constant Tsu : in time ) is
begin
if rising_edge(clock) then
assert data'last_event >= Tsu
report "setup time violation" severity error;
end if;
end procedure check_setup;
```
可以使用并发过程调用调用该过程:
```vhdl
check_ready_setup : check_setup ( data => ready,
clock => phi2,
Tsu => Tsu_rdy_clk );
```
当实际参数列表中的信号 `ready` 或 `phi2` 的值发生变化时,过程会被调用。过程返回后,并发过程调用语句会暂停,直到下一个信号事件发生。使用并发过程调用的优点有两个:一是可以编写一套常用的检查过程,并在需要时重复使用;二是调用检查的语句比等效的内联进程更紧凑、更易于理解。
如果没有与输入模式或输入输出模式参数关联的信号,等效进程中的等待语句将没有敏感列表。如果过程返回,进程将无限期暂停。这在希望过程仅在启动时调用一次时可能很有用。另一方面,也可以编写一个永远不返回的过程。如果在过程的循环中包含等待语句,它的行为有点像一个进程本身。这样做的优点是可以声明一个执行某些常用行为的过程,然后使用并发过程调用语句调用一个或多个实例。
#### 2. 函数
函数是 VHDL 中的另一种子程序。可以将函数看作是表达式的泛化,它定义了一种可以在表达式中使用的新操作。
##### 2.1 函数声明语法
函数声明的语法规则与过程声明非常相似:
```plaintext
subprogram_body ⇐
[ pure I impure ]
function identifier [ ( parameter_interface_list ) ] return type_mark is
{ subprogram_declarative_item }
begin
{ sequential_statement }
end [ function ] [ identifier ] ;
```
与过程不同,函数计算并返回一个可以在表达式中使用的结果。函数声明在关键字 `return` 之后指定结果的类型。函数的参数列表与过程的形式相同,但有两个限制:一是函数的参数不能是变量类型,如果未明确提及类,则假定为常量;二是每个参数的模式必须是输入模式,如果未明确指定模式,则假定为输入模式。
函数使用返回语句将计算结果传递给调用者,返回语句的语法规则如下:
```plaintext
return_statement ⇐ [ label : ] return expression ;
```
函数必须至少包含一个这样的返回语句,第一个执行的返回语句会使函数完成并将结果返回给调用者。函数不能简单地运行到函数体的末尾,因为这样无法提供一种指定要返回给调用者的结果的方法。
函数调用看起来与过程调用完全相同,但函数调用是表达式的一部分,而不是像过程调用那样单独的顺序语句。由于函数是作为表达式求值的一部分调用的,因此函数不允许包含等待语句(也不能调用包含等待语句的过程),表达式必须始终在单个仿真周期内求值。
##### 2.2 示例函数
- **限制值在范围内的函数**
```vhdl
function limit ( value, min, max : integer ) return integer is
begin
if value > max then
return max;
elsif value < min then
return min;
else
return value;
end if;
end function limit;
```
可以在变量赋值语句中调用该函数:
```vhdl
new_temperature := limit ( current_temperature
+ increment, 10, 100 );
```
也可以在进一步的计算中使用函数调用的结果:
```vhdl
new_motor_speed := old_motor_speed
+ scale_factor * limit ( error, -10, +10 );
```
- **位向量到数值转换函数**
```vhdl
function bv_to_natural ( bv : in bit_vector ) return natural is
variable result : natural := 0;
begin
for index in bv'range loop
result := result * 2 + bit'pos(bv(index));
end loop;
return result;
end function bv_to_natural;
```
在只读存储器模型中,可以使用该函数将地址端口的位向量转换为自然数值来索引 ROM 数据数组:
```vhdl
type rom_array is array (natural range 0 to rom_size-1)
of bit_vector(0 to word_size-1);
variable rom_data : rom_array;
data <= rom_data ( bv_to_natural(
```
0
0
复制全文
相关推荐










