task里可以使用always语句吗_Verilog HDL菜鸟学习笔记———五、一些基础知识

本文介绍了Verilog HDL中的基本概念,包括reg与wire的区别、阻塞赋值与非阻塞赋值的使用场景、parameter与`define及localparam的对比,以及task和function的功能和调用方式。同时,文章通过示例解释了generate生成块的用法,并提供了边沿检测电路的实现。
AI助手已提取文章相关产品:

(1)reg和wire的区别:

reg型数据保持最后一次的赋值,而wire型数据需要持续的驱动。wire用在连续赋值语句assign中;reg用于always过程赋值语句中。

wire对应于连续赋值,主要起信号间连接作用,用以构成信号的传递或者形成组合逻辑,如assign;reg对应于过程赋值,是寄存器的抽象表达,作用类似通常编程语言中的变量,可以储存数值,作为参与表达式的运算,通常负责时序逻辑,如always,initial。

Verilog中使用reg型,并不表示综合出来就是暂存器register:在组合电路中使用reg,组合后只是net;在时序电路中使用reg,合成后才是以Flip-Flop形式表示的register触发器。

(2)阻塞赋值和非阻塞赋值:

非阻塞(non-blocking) 赋值语句(b<= a):

1)块内的赋值语句同时赋值;

2)b的值被赋成新值a的操作, 是与块内其他赋值语句同时完成的;

3)建议在可综合风格的模块中使用非阻塞赋值。

阻塞(blocking) 赋值语句(b = a):

1)完成该赋值语句后才能做下一句的操作;

2)b的值立刻被赋成新值a;

3)硬件没有对应的电路,因而综合结果未知。

阻塞赋值和非阻塞赋值如果使用不当会存在冒险和竞争现象,必须按照下面两条准则:

1)在描述组合逻辑的always块中使用阻塞赋值,则综合组合逻辑的电路结构。

2) 在描述时序逻辑的always块中使用非阻塞赋值,则综合时序逻辑的电路结构。

在时钟沿触发的always块中,如果用非阻塞赋值语句对reg型变量赋值;或者当reg型变量经过多次循环其值仍保持不变,则会在综合中生成触发器。若不想生成触发器,而希望用reg型变量生成组合逻辑,则应使用电平触发。在组合逻辑中,阻塞赋值只与电平有关,往往和触发沿没有关系,可以将其看成并行执行的;在时序逻辑中,非阻塞赋值是并行执行的;因此,优秀的HDL设计,其内部语句也是并行执行的。

(3)parameter与define的区别,顺便说一下localparam:

`define:作用 -> 常用于定义常量可以跨模块、跨文件;

范围 -> 整个工程;

`define 从编译器读到这条指令开始到编译结束都有效,或者遇到`undef命令使之失效。

parameter:作用 -> 常用于模块间参数传递;

范围 -> 本module内有效的定义;

localparam:作用 -> 常用于状态机的参数定义;

范围 -> 本module内有效的定义,不可用于参数传递;

(4)task与function的区别,顺便说一下generate:

function的定义:

function

行为语句;

endfunction

定义function时,要注意以下几点:

1):function定义结构不能出现在任意一个过程块(always块或者initial块)的内部;

2):function定义不能包括有任何时间控制语句,即任何用#,@或wait来标识的语句;

3):定义function时至少要有一个输入参量;

4):定义function时,在function内部隐式地将函数名声明成一个寄存器变量,在函数体中必须有一条赋值语句对该寄存器变量赋以函数的结果值,以便调用function时能够得到返回的函数值。如果没有指定的返回值的宽度,function将缺省返回1位二进制数。

5):function的调用既可以出现在过程块中又可以出现在assign连续赋值语句之中。

function的调用:

(,...,) ;

task的定义

task;

端口与类型说明;

变量声明;

语句1;

。。。

语句n;

endtask

在定义一个task时,必须注意以下几点:

1):任务定义结构不能出现在任何一个过程块内;

2):一个task可以没有输入/输出端口,当然也可以有;

3): 一个task可以没有返回值,也可以通过输出端口或双向端口返回一个或多个值;

4):除任务参数外,task还能够引用说明任务的模块中定义的任何变量;

5):task调用是过程性语句,因此只能出现在always过程块和initial过程块中,调用task的输入与输出参数必须是寄存器类型的。在task中还可以调用其他的task和function。

task的调用:

task调用语句给出传入任务的参数值和接收结果的变量值,

(端口1,端口2,... ,端口n);

task和function的不同点:

1): function只能与主模块共用一个仿真时间单位,而task可以定义自己的仿真时间单位;

2): function不能调用任务,而task可以调用函数也可以调任务;

3): function至少需要一个输入变量,而task可以没有或者有很多个任意类型的变量;

4): function返回一个值,而task则不返回值。

generate生成块:

生成语句可以动态的生成verilog代码,当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者根据参数的定义来确定程序中是否应该包含某段Verilog代码的时候,使用生成语句能大大简化程序的编写过程。

生成语句生成的实例范围,关键字generate-endgenerate用来指定该范围。生成实例可以是以下的一个或多个类型:

1)模块;2)用户定义原语;3)门级语句;4)连续赋值语句;5)initial和always块。

generate语句有generate-for,generate-if,generate-case三种语句。以generate-for为例:

1)必须有genvar关键字定义for语句的变量。

2)for语句的内容必须加begin和end(即使就一句)。

3)for语句必须有个名字。

module test(bin,gray);

parameter SIZE=8;

output [SIZE-1:0] bin;

input [SIZE-1:0] gray;

genvar i; //genvar i;也可以定义到generate语句里面 generate

for(i=0;i

begin:bit

assign bin[i]=^gray[SIZE-1:i];

end

endgenerate

endmodule

等同于下面语句

assign bin[0]=^gray[SIZE-1:0];

assign bin[1]=^gray[SIZE-1:1];

assign bin[2]=^gray[SIZE-1:2];

assign bin[3]=^gray[SIZE-1:3];

assign bin[4]=^gray[SIZE-1:4];

assign bin[5]=^gray[SIZE-1:5];

assign bin[6]=^gray[SIZE-1:6];

assign bin[7]=^gray[SIZE-1:7];

另外一个例子

generate

genvar i;

for(i=0;i

begin:shifter

always@(posedge clk)

shifter[i]<=(i==0)?din:shifter[i-1];

end

endgenerate

相当于

always@(posedge clk)

shifter[0]<=din;

always@(posedge clk)

shifter[1]<=shifter[0];

always@(posedge clk)

shifter[2]<=shifter[1];

.................

......................

always@(posedge clk)

shifter[SIZE]<=shifter[SIZE-1];

(5) 用verilog实现边沿检测电路:上升沿,下降沿,双沿(上升或下降沿)。

module edge_detect(clk,rst,signal,pos_edge,neg_edge,both_edge);

input clk;

input rst;

input signal;

output pos_edge;

output neg_edge;

output both_edge;

reg sig_r0,sig_r1;//状态寄存器 always @(posedge clk)

begin

if(rst)

begin

sig_r0 <= 1'b0;

sig_r1 <= 1'b0;

end

else

begin

sig_r0 <= signal;

sig_r1 <= sig_r0;

end

end

assign pos_edge = ~sig_r1 & sig_r0;

assign neg_edge = sig_r1 & ~sig_r0;

assign both_edge = sig_r0 ^ sig_r1;

endmodule

『文末说明』

本文作者:小强子

知乎ID:Power小强

永远年轻,永远热泪盈眶,永远充满希望,一个嗜好太多能力又太小的普通人。

您可能感兴趣的与本文相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值