(原创)task和function语法的使用讨论(Verilog,CPLD/FPGA)
1. Abstract
function和task语句的功能有很多的相似之处,在需要有多个相同的电路生成时,可以考虑使用它们来实现。因为个人使用它们比较少,所以对它们没有进行更深的了解,现在时间比较充裕,我想通过写几个简单的电路将它们二者的功能进行验证一下,看看究竟是怎么生成电路的。
2. Contents
主要为测试function和task各自生成的电路,所以电路设计功能比较简单——4位BCD码转换成4位余3码。
文件开头的注释说明。
/* ---------------------------------------
Module Name: temp
Module Function: 将4位BCD码转换成为余3码,无效状态为4'b0000
Module Input: 4-bit data_in
Module Output: 4-bit data_out
Module Reference: None
Note: 码表如下
########################################
data_in data_out
0 4'b0000 4'b0011
1 4'b0001 4'b0100
2 4'b0010 4'b0101
3 4'b0011 4'b0110
4 4'b0100 4'b0111
5 4'b0101 4'b1000
6 4'b0110 4'b1001
7 4'b0111 4'b1010
8 4'b1000 4'b1011
9 4'b1001 4'b1100
10 4'b1010 4'b0000 无效
11 4'b1011 4'b0000 无效
12 4'b1100 4'b0000 无效
13 4'b1101 4'b0000 无效
14 4'b1110 4'b0000 无效
15 4'b1111 4'b0000 无效
---------------------------------------*/
2.1 直接使用组合逻辑电路生成BCD码转余3码。
module temp(data_in,data_out); output reg [:] data_out;
input [:] data_in; always @(data_in)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else data_out = data_in + 'd3;
end endmodule
用RTL视图查看一下生成出来的网表
FIG2.1 直接用组合逻辑生成的逻辑图
生成出来的电路由加法器、比较器和选择器构成,输入数据data_in + 3作为选择器的选择控制,下面做一下验证测试。
FIG2.2 测试仿真验证
2.2 用task语句编写组合电路
module temp(data_in,data_out); output reg [:] data_out;
input [:] data_in; always @(data_in)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else BCD2Access3(data_out,data_in);
end task BCD2Access3;
output [:] data_out;
input [:] data_in; data_out = data_in + 'd3;
endtask
endmodule
用RTL视图查看一下最后生成的网表。
FIG2.3 使用task语句生成出的逻辑图
仔细对比,FIG2.3和FIG2.1是一模一样的,也就是说采用task语句可以生成预期的逻辑图,非常成功!既然生成出的逻辑图都是一样的,测试部分在此就省略了吧,和FIG2.2应该是一样的。
2.3 用function语句编写组合逻辑
module temp(data_in,data_out); output reg [:] data_out;
input [:] data_in; always @(data_in)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else data_out = BCD2Access3(data_in);
end function [:] BCD2Access3;
input [:] data_in; BCD2Access3 = data_in + 'd3;
endfunction
endmodule
用RTL视图查看一下最后生成出来的网表。
FIG2.4 使用function语句生成出的逻辑图
相信已经很熟悉这个逻辑图了,与前面的FIG2.1一模一样,也就是说使用function语句也是可以生成预期的电路的,而且也是非常成功的!既然逻辑图都是与前面一致的,故测试部分……也省去了吧。
小结一下,用function和task语句都可以生成预期的逻辑电路,不过,查查语法书,可以知道task语句的适用性更广泛一点,更符合逻辑思维的习惯;function最大的好处就是可以有一个返回值,运算以后结果可以直接返回供调用的块使用。
在组合逻辑设计的过程中,写成可综合的电路可以达到预期的生成电路逻辑,那么在时序逻辑设计中,function和task语句又会生成出怎样的电路呢?还是以这一个电路功能为模板,值得注意的是,得额外加一个时钟信号。
2.4 直接使用时序逻辑编写的BCD码转余3码。
module temp(data_in,data_out,clk); output reg [:] data_out;
input [:] data_in;
input clk; always @(posedge clk)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else data_out <= data_in + 'd3;
end endmodule
用RTL视图来看下生成出来的逻辑网表。
FIG2.5 直接用时序逻辑编写生成的逻辑网表
和上面生成的逻辑网表相比,多了一个锁存器,这也是典型的时序逻辑的特征,数据的变化只在clk的上升沿才有效。下面来做一下电路逻辑的验证。
FIG2.6 时序逻辑网表的验证
图确实有点小,可能看起来有点不方便,但逻辑的功能是正确的,每到clk的上升沿,数据更新一次,译码是正确的,为了方便看,再截取一部分出来吧,作为一个局部放大图。
FIG2.7 时序逻辑验证的局部放大图
直接用时序逻辑设计成功了,再尝试着用task语句和function语句实现,看看最后的效果会怎么样。
2.5 时序逻辑下使用task语句实现电路
module temp(data_in,data_out,clk); output reg [:] data_out;
input [:] data_in;
input clk; always @(posedge clk)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else BCD2Access3(data_out,data_in);
end task BCD2Access3;
output [:] data_out;
input [:] data_in; data_out = data_in + 'd3;
endtask endmodule
用RTL视图来看一下生成的逻辑网表。
FIG2.8 使用task语句生成的逻辑网表
同样,仔细对照一下,发现FIG2.8和FIG2.6是一样的,也就是说在时序逻辑中使用task语句也是可以实现预期的电路的,非常的成功!和上述讨论的一样,既然逻辑图相同的话,验证的部分就略去了吧。
2.6 时序逻辑下用function语句实现电路
module temp(data_in,data_out,clk); output reg [:] data_out;
input [:] data_in;
input clk; always @(posedge clk)
begin
if(data_in >= 'd10) data_out = 4'b0000;
else data_out <= BCD2Access3(data_in);
end function [:] BCD2Access3;
input [:] data_in; BCD2Access3 = data_in + 'd3;
endfunction endmodule
跟上面一样,用RTL视图来看看最后生成出来的电路。
FIG2.9 时序逻辑下使用function语句生成的逻辑网表
仔细对比,会发现跟如上的逻辑网表一样,也就是说在时序逻辑下使用function语句也是可以实现预期的电路的,非常的成功!逻辑网表一致的话,在此逻辑的验证容我略去吧。
小结一下,在时序逻辑的电路设计中,也可以使用task语句和function语句来实现电路。
在学习过程中,也不断的在看语法书,毕竟这一块是我不太熟悉的地方,现在将它们使用的一些要点整理出来,对如何使用和最后生成怎样的很有参考帮助。
task语句要点
(1)若用于任务中的命名变量或参数没有在任务块中声明,则指的是在模块中声明的命名变量或参数。
(2)任务中的input,output和inout的个数不受限制(也可以为0个)。(任务可以没有参数)
(3)任务中的变量(包括输入(input)和双向端口(inout))可以声明为寄存器型。如果没有明确地声明,则默认为寄存器类型,且其位宽与相应的变量匹配。
(4)当启动任务时,相应于任务的输入和双向端口(inout)的变量表达式的值被存入相应的变量寄存器中。当任务结束时,输入和双向端口(inout)的变量寄存器中的值又被代入启动任务的语句中相应的表达式。
电路综合参考:包含时序控制语句的任务是不可综合的。启动的任务往往被综合成组合逻辑。
function语句要点
(1)函数必须至少有一个输入变量,不能有任何输出或输入/输出双向变量(output 和inout类型)。
(2)函数不能包含时间控制语句(如延迟#、事件控制@或者等待wait)。
(3)函数是通过对函数名赋值的途径返回其值的,就好比是一个寄存器。
(4)函数不能启动任务。
(5)函数不能被禁用。(特指应用于编写测试文件)
电路综合参考:函数的每一次调用都被综合为一个独立的组合逻辑电路块。
3.Conclusion
总体来说,task的功能更加符合硬件逻辑设计的习惯,而且语法中对它的限制比较少。而且它们最终生成的电路都是组合逻辑,所以在需要产生多个相同的模块时,可以采用由它们构成。
4.Platform
Quartus II 9.1 Build 222 Full Version
5.Reference
[1] Verilog 数字系统设计教程(第2版) 夏宇闻
[2] Advanced Digital Design with the Verilog HDL (Second Edition) Michael D.Ciletti
(原创)task和function语法的使用讨论(Verilog,CPLD/FPGA)的更多相关文章
- vivado对task和function的可综合支持
手册UG901,对vivado可综合的语句支持进行了描述,HDL包括:verilog-2001,system-verilog,VHDL: verilog-2001扩展了对task和function的支 ...
- SV中的task和function
SV中class的properties和methods默认都是public的,但是可以声明为local和protected. 一个properties声明为local类型的,则只在该class中的me ...
- with function 语法支持
通过with子句,我们可以把很多原本需要存储过程来实现的复杂逻辑用一句SQL来进行表达.KingbaseES 从V008R006C004B0021 版本开始,支持 with function 语法.例 ...
- new Function()语法
函数的语法: let func = new Function(...args, body); 历史原因,参数也可以以逗号分隔的列表的形式给出,这三个意思相同: new Function('a', 'b ...
- Oracle存储过程function语法及案例
create or replace function F01_SX03_SUM(statdate varchar2, code varchar2, para varchar2) RETURN numb ...
- (原创)defparam的应用(Verilog,CPLD/FPGA)
1.Abstract 在同一个模块被多次例化的时候,改变参数构建不同的硬件实体是一个很好的选择.特别是今天帮一个朋友调试一个比较复杂的逻辑,深有体会.这个也是一个小技巧,回来也查了许多资料,强 ...
- (原创)用Verilog实现一个参数化的呼吸灯(Verilog,CPLD/FPGA)
1.Abstract 观察到一个有趣的现象,每当把Apple笔记本合上的时候,那个白色的呼吸灯就会反复地由暗渐明,然后又由明渐暗,乍一看就像Apple笔记本在打盹休息一样,十分可爱!于是突发奇 ...
- (原创)基于FPGA的调光流水灯(Verilog,CPLD/FPGA)
1.Abstract 前几天做了一个呼吸灯,觉得确实挺有意思的:可惜的是只有一个灯管亮,板子上有四个灯,要是能让这些灯有序地亮起来,那应该更有趣味了!跟传统的一样,逻辑上做成一个流水灯的样式, ...
- function返回值Python特殊语法:filter、map、reduce、lambda
废话就不多说了,开始... Python内置了一些非常有趣但非常有用的函数,充分体现了Python的语言魅力! filter(function, sequence):对sequence中的item顺次 ...
随机推荐
- java(itext) 一个很简单的PDF表格生成工具
先上个效果图 因为做的项目涉及到数据预测,其中有大量打印业务来支撑实体店的运营,因为注重的是数据,要求简洁,清晰,所以写了个很简单也很实用的工具类. 如果需要编写样式或者插入背景,都可以查阅itex官 ...
- MySQL学习系列2--MySQL执行计划分析EXPLAIN [原创]
1.Explain语法 EXPLAIN SELECT …… 变体: EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可 ...
- Callable的简单使用
说起java的线程操作,都会想到Thread和Runable这两个, 这两个类可以实现异步和同步. 在大多数的java开发中, 这两个都是实现异步的线程来使用, 但是现在考虑一种情况: 发出一条线程, ...
- zabbix-3.4 触发器
3 触发器 概述 触发器是"评估"由项目采集的数据并表示当前系统状况的逻辑表达式. 当监控项用于采集系统的数据时,始终遵循这些数据是非常不切合实际的,因为这些数据始终在等待一个令人 ...
- SqlServer Alwayson主副本图标显示问号的原因
搭建完alwayson后,登录辅助副本服务器,查看alwayson可用性副本列表,看到主副本前面显示了一个问号,这里借用网上一张图片做展示: 在显示问号的主副本上右键属性查看,“角色”一栏中,显示的是 ...
- 用rem实现h5页面的编写
一 静态页面的布局 将这段代码加到script中 (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orienta ...
- ABAP Netweaver和Cloud Foundry上的环境变量Environment Variable
Netweaver 更准确的说应该是系统变量:结构体sy 设一个断点,调试器里看这些字段的值就能知道每个字段是用来做什么的. sy-dbsys sy-sysid sy-opsys sy-saprl s ...
- POJ 2392 Space Elevator(多重背包)
显然塔的总高度不会超过最大的a[i],而a[i]之前的可以到达的高度 是由a值更小的块组成,所以按照a从小到大的顺序去转移. 然后就是多重背包判断存在性了,几乎和coin那题一样. 数据没coin丧病 ...
- MAC 设置登录欢迎语
MacdeMacBook-Pro:etc mac$ cd /etc MacdeMacBook-Pro:etc mac$ cat motd 技术沉淀,空杯心态! _______ _______ _ __ ...
- 生成.m文件的python代码中出现的错误
错误代码 import tempfile import subprocess import shlex import os import numpy as np import scipy.io scr ...