函数function
关键词:函数,大小端转换,数码管译码
用任务(关键字为 task)或函数(关键字为 function),将重复性的行为级设计进行提取,并在多个地方调用
函数
- 不含有任何延迟、时序或时序控制逻辑
- 至少有一个输入变量
- 只有一个返回值,且没有输出
- 不含有非阻塞赋值语句
- 函数可以调用其他函数,但是不能调用任务
函数在声明时,会隐式的声明一个宽度为 range、 名字为 function_id 的寄存器变量,函数的返回值通过这个变量进行传递。当该寄存器变量没有指定位宽时,默认位宽为 1。
常数函数
在编译期间就计算出结果为常数的函数。
常数函数不允许访问全局变量或者调用系统函数,但是可以调用另一个常数函数。
这种函数能够用来引用复杂的值,因此可用来代替常量。
automatic 函数
用关键字 automatic
来对函数进行说明,此类函数在调用时是可以自动分配新的内存空间的,也可以理解为是可递归的。
automatic 函数中声明的局部变量不能通过层次命名进行访问,但是 automatic 函数本身可以通过层次名进行调用。
任务task
关键词:任务
和函数一样,任务(task)可以用来描述共同的代码段,并在模块内任意位置被调用
函数一般用于组合逻辑的各种转换和计算,而任务更像一个过程,不仅能完成函数的功能,还可以包含时序控制逻辑
任务与函数的区别
任务
任务声明
任务在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块。
模块内子程序出现下面任意一个条件时,则必须使用任务而不能使用函数。
- 子程序中包含时序控制逻辑,例如延迟,事件控制等
- 没有输入变量
- 没有输出或输出端的数量大于 1
把 input 声明的端口变量看做 wire 型,把 output 声明的端口变量看做 reg 型
对 output 信号赋值时也不要用关键字 assign。为避免时序错乱,建议 output 信号采用阻塞赋值。
任务调用
任务可单独作为一条语句出现在 initial 或 always 块中
task_id(input1, input2, …,outpu1, output2, …);
任务调用时,端口必须按顺序对应
- 输入端连接的模块内信号可以是 wire 型或 reg 型。
- 输出端连接的模块内信号要求一定是 reg 型
任务操作全局变量
任务可以看做是过程性赋值,所以任务的 output 端信号返回时间是在任务中所有语句执行完毕之后
任务内部变量也只有在任务中可见,如果想具体观察任务中对变量的操作过程,需要将观察的变量声明在模块之内、任务之外,可谓之"全局变量"。
automatic 任务
- 任务调用时各存储空间就可以动态分配,每个调用的任务都各自独立的对自己独有的地址空间进行操作,而不影响多个相同任务调用时的并发执行。
- 如果一任务代码段被 2 处及以上调用,一定要用关键字 automatic 声明(否则可能出现信号间干扰)。
状态机
关键词:状态机,售卖机
状态机类型
Moore 型状态机
输出只与当前状态有关,与当前输入无关。
输出会在一个完整的时钟周期内保持稳定,即使此时输入信号有变化,输出也不会变化。输入对输出的影响要到下一个时钟周期才能反映出来。这也是 Moore 型状态机的一个重要特点:输入与输出是隔离开来的。
Mealy 型状态机
不仅与当前状态有关,还取决于当前的输入信号
Mealy 型状态机的输出是在输入信号变化以后立刻发生变化,且输入变化可能出现在任何状态的时钟周期内。
同种逻辑下,Mealy 型状态机输出对输入的响应会比 Moore 型状态机早一个时钟周期。