Verilog的always块内的常见问题:边沿电平、同步异步、阻塞非阻塞

0引言

verilog的always块内的边沿电平、同步异步、阻塞非阻塞问题,往往令初学者头大,下面我记录一下上述三种条件不同情况下的verilog代码描述、综合结果和资源占用情况,以供参考。
平台1:xilinx
工具: vivado 2019.2
芯片选型:zynq-7020(ps:zynq-7000系列 为lut6)

1.always块多边沿触发问题

Q1:一个always块内是如何实现异步复位的?

code case 1.1:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case1.1
always@(posedge clk or negedge rstn)
	if(~rstn )
		C <= B&A;
	else
		C <=1'b0;			
endmodule

上为一般的带有异步复位的always逻辑块,时钟边沿获取A&B的值赋给reg C,异步低复位置C零。

综合电路如下:
图1
消耗资源情况:
LUT - 3    FF - 1
可以看到真正的触发边沿信号只有一个clk(PDFE),而另一个边沿rstn被处理为组合逻辑,异步复位体现为把D触发器的输出与带有复位的组合逻辑并列,值得注意的是通常原理图助记符号对异步的描述很简单,即直接加在D触发器上,如下图,但实际上一个D触发器不具备这种异步复位功能,而必须依赖额外的组合逻辑资源来实现,这从消耗Lut资源为3而不是1也可以侧面看出。
在这里插入图片描述

Q2:一个异步复位always块内是如何识别哪个是触发时钟哪个是复位?

code case1.2

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case1.2
always@(posedge clk or negedge rstn)
	if(~clk )
		C <= B&A;
	else
		C <=1'b0;	
endmodule

上述相比case1.1 将判断信号从rstn换成clk,综合结果如下:
在这里插入图片描述
资源消耗:LUT-3    FF-1
结果显示rstn为边沿触发,clk为复位。
这说明,双边沿触发信号,参与逻辑运算的信号可以作为异步信号,默认的不参与的作为时钟触发。

Q3:always块内3个或者以上的边沿信号如何处理?

code case 1.3

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case1.3
always@(posedge clk or negedge rstn or posedge clk1)
	if(~clk )
		C <= B&A;
	else
		C <=1'b0;	
endmodule

在case1.2基础上再引入触发信号clk1,并在判断逻辑中对rstn和clk1均不限定,而仅限定一个clk。
综合结果:错误
[Synth 8-91] ambiguous clock in event control (模糊时钟)

Q4:进一步限定clk1会怎样?

code case 1.4:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case1.4
always@(posedge clk or negedge rstn or posedge clk1)
	if(~clk &&  clk1 )
		C <= B&A;
	else
		C <=1'b0;	
endmodule

综合结果如下:
在这里插入图片描述
说明,默认未限定的rstn,为当作边沿触发信号,其他两个clk,clk1被条件判断限定成电平方式的组合逻辑。

Q5:对所有的边沿触发都加入条件判断限定会怎样?

code case 1.5:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case1.5
always@(posedge clk or negedge rstn or posedge clk1)
	if( ~rstn &&  clk1 && ~clk )
		C <= B&A;
	else
		C <=1'b0;	
endmodule

综合结果:
在这里插入图片描述
此时仍然有一个信号clk被选作出发边沿,此时3个信号都参与到条件逻辑判断运算中。可以进一步验证,更换信号位置
if( ~rstn && clk1 && ~clk ) 为 if( clk1 && ~clk && ~rstn ) , rstn 会被选作边沿触发。 也即,与表达式中的最后一个被编译器选作D触发器的边沿触发信号。

小节:

多边沿触发时,实际只有一个作为D触发器的边沿触发信号,该信号为代码块中默认未提及的或者与表达式最后的一个(其他情况未验证),不能留1个以上不约束边沿触发信号,否则出现ambiguous clock in event control 错误。

2.always块同步复位

code case 2:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case2
always@(posedge clk)
	if(~rstn )
		C <= B&A;
	else
		C <= 1'b0;	
endmodule

同步复位即触发信号仅为clk,rstn不加入触发。

综合结果:
在这里插入图片描述
占用资源:
LUT - 1   FF - 1

结果显示

复位信号经过反相后直接接到FF中。这进一步说明,一个FF自带的复位为同步复位,如果要异步复位需要额外的组合逻辑资源。同时,表明该型号fpga的复位信号默认高有效,如果需要低电平有效,必须要引入一个反相器。有论坛讨论,大部分xilinx的fpga都是高电平复位,altera则是低电平复位,遵守这个规则能够降低延时和资源占用。

3.always块边沿触发、阻塞赋值

code case 3:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case3
always@(posedge clk)
	if(~rstn )
		C = B&A;
	else
		C = 1'b0;	
endmodule

注意,此时的reg型信号 C 使用了 阻塞赋值“=” 。
综合结果:
在这里插入图片描述
资源占用:
LUT - 1   FF - 1

结果显示

边沿触发、阻塞赋值,综合结果与case 2 中的非阻塞赋值一样。这说明:

  1. always块内的reg变量可以进行阻塞赋值,而我们知道assign语句中,reg变量不能放在等号左边被赋值,会报错[Synth 8-1852] concurrent assignment to a non-net C is not permitted 。
  2. 结果与case 2的非阻塞赋值一样,生成带有FF的时序逻辑。

4.always块电平触发、阻塞赋值

code case 4:

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case4
always@(*)
	if(~rstn )
		C = B&A;
	else
		C = 1'b0;	
endmodule

即去掉触发信号的关键词 posedge 和 negedge,仅用信号名,或者“ * ”代表所有信号。
综合结果:
在这里插入图片描述
资源占用:
LUT - 1   FF - 0

结果显示

1.电平触发+阻塞赋值,always块生成纯组合逻辑。
2.reg型的变量,生成的可以不带FF,可以是纯组合逻辑。
3.把触发电平信号换成 A、B、rstn、clk都不影响综合结果,说明编译器判断规则是只要没有posedge和negedge关键词,都一律判定为无需触发,时时生效,即组合逻辑。

5.always块电平触发、非阻塞赋值

code case 5

module block(clk,clk1,rstn,A, B,C);
input clk,clk1,rstn,A,B;
output reg C;
//case5
always@(*)
	if(~rstn )
		C <= B&A;
	else
		C <= 1'b0;	
endmodule

同样,*可以是 A、B、rstn、clk
综合结果:
在这里插入图片描述
资源占用:
LUT - 1   FF - 0

结果显示
  1. 为纯组合逻辑,与case4 结果一模一样。
  2. always块内的reg变量的非阻塞赋值也可能生成不带FF的组合逻辑。

总结

  1. 同步异步复位问题:FF自带的复位默认为同步复位,要实现异步必须消耗额外的组合逻辑资源,而同步则不用。
  2. 多边沿触发:只允许一个实际触发时钟接入FF的触发端,其他的触发信号都必须给出限制从而被综合成电平信号组合逻辑。
  3. always块内生成的带不带DFF,取决于触发信号是否带有 posedge 和 negedge关键字,在可综合情况下,有则必然为带触发器的时序逻辑,无则为无触发器的组合逻辑,而无关是否阻塞非阻塞。(PS: 语法上,assign 的被赋值变量是必须是wire, always块内的被赋值变量必须是reg)

最后如果觉得有用,烦请点赞、收藏一下。

  • 16
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
目 录 译者序 前言 第1章 简介 1 1.1 什么是Verilog HDL? 1 1.2 历史 1 1.3 主要能力 1 第2章 HDL指南 4 2.1 模 4 2.2 时延 5 2.3 数据流描述方式 5 2.4 行为描述方式 6 2.5 结构化描述形式 8 2.6 混合设计描述方式 9 2.7 设计模拟 10 第3章 Verilog语言要素 14 3.1 标识符 14 3.2 注释 14 3.3 格式 14 3.4 系统任务和函数 15 3.5 编译指令 15 3.5.1 `define和`undef 15 3.5.2 `ifdef、`else 和`endif 16 3.5.3 `default_nettype 16 3.5.4 `include 16 3.5.5 `resetall 16 3.5.6 `timescale 16 3.5.7 `unconnected_drive和 `nounconnected_drive 18 3.5.8 `celldefine 和 `endcelldefine 18 3.6 值集合 18 3.6.1 整型数 18 3.6.2 实数 19 3.6.3 字符串 20 3.7 数据类型 20 3.7.1 线网类型 20 3.7.2 未说明的线网 23 3.7.3 向量和标量线网 23 3.7.4 寄存器类型 23 3.8 参数 26 第4章 表达式 28 4.1 操作数 28 4.1.1 常数 28 4.1.2 参数 29 4.1.3 线网 29 4.1.4 寄存器 29 4.1.5 位选择 29 4.1.6 部分选择 29 4.1.7 存储器单元 30 4.1.8 函数调用 30 4.2 操作符 30 4.2.1 算术操作符 31 4.2.2 关系操作符 33 4.2.3 相等关系操作符 33 4.2.4 逻辑操作符 34 4.2.5 按位操作符 35 4.2.6 归约操作符 36 4.2.7 移位操作符 36 4.2.8 条件操作符 37 4.2.9 连接和复制操作 37 4.3 表达式种类 38 第5章 门电平模型化 39 5.1 内置基本门 39 5.2 多输入门 39 5.3 多输出门 41 5.4 三态门 41 5.5 上拉、下拉电阻 42 5.6 MOS开关 42 5.7 双向开关 44 5.8 门时延 44 5.9 实例数组 45 5.10 隐式线网 45 5.11 简单示例 46 5.12 2-4解码器举例 46 5.13 主从触发器举例 47 5.14 奇偶电路 47 第6章 用户定义的原语 49 6.1 UDP的定义 49 6.2 组合电路UDP 49 6.3 时序电路UDP 50 6.3.1 初始化状态寄存器 50 6.3.2 电平触发的时序电路UDP 50 6.3.3 边沿触发的时序电路UDP 51 6.3.4 边沿触发电平触发的混合行为 51 6.4 另一实例 52 6.5 表项汇总 52 第7章 数据流模型化 54 7.1 连续赋值语句 54 7.2 举例 55 7.3 线网说明赋值 55 7.4 时延 55 7.5 线网时延 57 7.6 举例 57 7.6.1 主从触发器 57 7.6.2 数值比较器 58 第8章 行为建模 59 8.1 过程结构 59 8.1.1 initial 语句 59 8.1.2 always语句 61 8.1.3 两类语句在模中的使用 62 8.2 时序控制 63 8.2.1 时延控制 63 8.2.2 事件控制 64 8.3 语句 65 8.3.1 顺序语句 66 8.3.2 并行语句 67 8.4 过程性赋值 68 8.4.1 语句内部时延 69 8.4.2 阻塞性过程赋值 70 8.4.3 非阻塞性过程赋值 71 8.4.4 连续赋值与过程赋值的比较 72 8.5 if 语句 73 8.6 case语句 74 8.7 循环语句 76 8.7.1 forever 循环语句 76 8.7.2 repeat 循环语句 76 8.7.3 while 循环语句 77 8.7.4 for 循环语句 77 8.8 过程性连续赋值 78 8.8.1 赋值—重新赋值 78 8.8.2 force与release 79 8.9 握手协议实例 80 第9章 结构建模 83 9.1 模 83 9.2 端口 83 9.3 模实例语句 83 9.3.1 悬空端口 84 9.3.2 不同的端口长度 85 9.3.3 模参数值 85 9.4 外部端口 87 9.5 举例 89 第10章 其他论题 91 10.1 任务 91 10.1.1 任务定义 91 10.1.2 任务调用 92 10.2 函数 93 10.2.1 函数说明部分 93 10.2.2 函数调用 94 10.3 系统任务和系统函数 95 10.3.1 显示任务 95 10.3.2 文件输入/输出任务 97 10.3.3 时间标度任务 99 10.3.4 模拟控制任务 99 10.3.5 定时校验任务 100 10.3.6 模拟时间函数 101 10.3.7 变换函数 102 10.3.8 概率分布函数 102 10.4 禁止语句 103 10.5 命名事件 104 10.6 结构描述方式和行为描述方式的 混合使用 106 10.7 层次路径名 107 10.8 共享任务和函数 108 10.9 值变转储文件 110 10.9.1 举例 111 10.9.2 VCD文件格式 112 10.10 指定程序 113 10.11 强度 114 10.11.1 驱动强度 114 10.11.2 电荷强度 115 10.12 竞争状态 116 第11章 验证 118 11.1 编写测试验证程序 118 11.2 波形产生 118 11.2.1 值序列 118 11.2.2 重复模式 119 11.3 测试验证程序实例 123 11.3.1 解码器 123 11.3.2 触发器 124 11.4 从文本文件中读取向量 126 11.5 向文本文件中写入向量 127 11.6 其他实例 128 11.6.1 时钟分频器 128 11.6.2 阶乘设计 130 11.6.3 时序检测器 132 第12章 建模实例 136 12.1 简单元件建模 136 12.2 建模的不同方式 138 12.3 时延建模 139 12.4 条件操作建模 141 12.5 同步时序逻辑建模 142 12.6 通用移位寄存器 145 12.7 状态机建模 145 12.8 交互状态机 147 12.9 Moore有限状态机建模 150 12.10 Mealy型有限状态机建模 151 12.11 简化的21点程序 153 附录 语法参考 157 参考文献 172
目 录 译者序 前言 第1章 简介 1 1.1 什么是Verilog HDL? 1 1.2 历史 1 1.3 主要能力 1 第2章 HDL指南 4 2.1 模 4 2.2 时延 5 2.3 数据流描述方式 5 2.4 行为描述方式 6 2.5 结构化描述形式 8 2.6 混合设计描述方式 9 2.7 设计模拟 10 第3章 Verilog语言要素 14 3.1 标识符 14 3.2 注释 14 3.3 格式 14 3.4 系统任务和函数 15 3.5 编译指令 15 3.5.1 `define和`undef 15 3.5.2 `ifdef、`else 和`endif 16 3.5.3 `default_nettype 16 3.5.4 `include 16 3.5.5 `resetall 16 3.5.6 `timescale 16 3.5.7 `unconnected_drive和 `nounconnected_drive 18 3.5.8 `celldefine 和 `endcelldefine 18 3.6 值集合 18 3.6.1 整型数 18 3.6.2 实数 19 3.6.3 字符串 20 3.7 数据类型 20 3.7.1 线网类型 20 3.7.2 未说明的线网 23 3.7.3 向量和标量线网 23 3.7.4 寄存器类型 23 3.8 参数 26 第4章 表达式 28 4.1 操作数 28 4.1.1 常数 28 4.1.2 参数 29 4.1.3 线网 29 4.1.4 寄存器 29 4.1.5 位选择 29 4.1.6 部分选择 29 4.1.7 存储器单元 30 4.1.8 函数调用 30 4.2 操作符 30 4.2.1 算术操作符 31 4.2.2 关系操作符 33 4.2.3 相等关系操作符 33 4.2.4 逻辑操作符 34 4.2.5 按位操作符 35 4.2.6 归约操作符 36 4.2.7 移位操作符 36 4.2.8 条件操作符 37 4.2.9 连接和复制操作 37 4.3 表达式种类 38 第5章 门电平模型化 39 5.1 内置基本门 39 5.2 多输入门 39 5.3 多输出门 41 5.4 三态门 41 5.5 上拉、下拉电阻 42 5.6 MOS开关 42 5.7 双向开关 44 5.8 门时延 44 5.9 实例数组 45 5.10 隐式线网 45 5.11 简单示例 46 5.12 2-4解码器举例 46 5.13 主从触发器举例 47 5.14 奇偶电路 47 第6章 用户定义的原语 49 6.1 UDP的定义 49 6.2 组合电路UDP 49 6.3 时序电路UDP 50 6.3.1 初始化状态寄存器 50 6.3.2 电平触发的时序电路UDP 50 6.3.3 边沿触发的时序电路UDP 51 6.3.4 边沿触发电平触发的混合行为 51 6.4 另一实例 52 6.5 表项汇总 52 第7章 数据流模型化 54 7.1 连续赋值语句 54 7.2 举例 55 7.3 线网说明赋值 55 7.4 时延 55 7.5 线网时延 57 7.6 举例 57 7.6.1 主从触发器 57 7.6.2 数值比较器 58 第8章 行为建模 59 8.1 过程结构 59 8.1.1 initial 语句 59 8.1.2 always语句 61 8.1.3 两类语句在模中的使用 62 8.2 时序控制 63 8.2.1 时延控制 63 8.2.2 事件控制 64 8.3 语句 65 8.3.1 顺序语句 66 8.3.2 并行语句 67 8.4 过程性赋值 68 8.4.1 语句内部时延 69 8.4.2 阻塞性过程赋值 70 8.4.3 非阻塞性过程赋值 71 8.4.4 连续赋值与过程赋值的比较 72 8.5 if 语句 73 8.6 case语句 74 8.7 循环语句 76 8.7.1 forever 循环语句 76 8.7.2 repeat 循环语句 76 8.7.3 while 循环语句 77 8.7.4 for 循环语句 77 8.8 过程性连续赋值 78 8.8.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值