我的 FPGA 学习历程(15)—— Verilog 的 always 语句综合
在本篇里,我们讨论 Verilog 语言的综合问题,Verilog HDL (Hardware Description Language) 中文名为硬件描述语言,而不是硬件设计语言。这个名称提醒我们是在描述硬件,即用代码画图。
在 Verilog 语言中,always 块是一种常用的功能模块,也是结构最复杂的部分。笔者初学时经常为 always 语句的编写而苦恼,不知道使用哪种赋值语句,不了解两种赋值之间的区别。究其本质是对 always 语句的综合一知半解,常年使用软件思维编写代码所致。
现在我总结出:always 块的综合可以分为至少三类电路,由于历史原因,三种电路均使用 always 关键字。
此外 reg 关键字也存在一些迷惑性,综合器并不一定生成寄存器。
reg 在 verilog 语法中的定义为变量,它有可能是寄存器,也有可能是连线。
第一类就是组合逻辑,如代码 1-1 和 代码 1-2
// 1-1 组合逻辑
always @ (*)
begin
if(a>b)
q = 1;
else
q = 0;
end
代码 1-1 是展示了一个简单组合逻辑的 always 块,它应该被综合成一个一位的比较器。
// 1-2 组合逻辑,缺少敏感信号
always @ (a)
begin
if(a>b)
q = 1;
else
q = 0;
end
代码 1-2 也是一个组合逻辑,与 1-1 不同的是,敏感信号列表中没有 b。
我们知道,在 Verilog 语法中, always 块的含义是一个重复执行的语句。
那么 1-2 会综合成一个比较器:
- 当 a 发生变化时,q 发生变化
- 当 b 发生变化,由于 b 不再敏感信号列表中,所以 q 不变
这是一个彻头彻尾的软件思维,世界上不存在这种电路,综合器多半会综合一个与代码 1-1 一样的电路,然后报一个警告。
编写组合逻辑的 always 块,使用 * 代替敏感信号列表是一个简单方便而且不容易出错的好办法。
第二类就是时序逻辑
// 2-1 时序逻辑
reg [1:0] q;
always @ (posedge clk)
begin
q <= q + 1'b1;
end
注意:这里使用的是阻塞赋值,我们的 q 这个时候被综合成一个寄存器,而不是一个软件上的变量。
代码 2-1 是一个时序逻辑单元,它应该被综合成一个计数器,每当时钟的上升沿,q 自增一。综合后的 部分 RTL 图如下:

我们可以看到,q 通过了一个加法器,加法器是两位的。
而关键的 always 块的综合结果如下图所示:

我们可以看到,always 块综合了一个时钟上升沿触发的 D 触发器。每当时钟的上升沿,D 触发器就把输入 D 传递到另一侧 Q。
综合器就这样完成了我们的设计意图:D 的左侧总是等于 Q+1,只有在 时钟的上升沿,才完成值的传递。完整的RTL 图如下:

// 2-2 时序逻辑,带异步复位
reg [1:0] q;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
q <= 2'b00;
else
q <= q + 1'b1;
end
综合后的 RTL 图如下:

代码2-2综合成一个带有清零端的 D 触发器,其余与 2-1 无异。
// 2-3 时序逻辑,带同步置位
reg [1:0] q;
always @ (posedge clk or posedge set)
begin
if(set)
q <= 2'b11;
else
q <= q + 1'b1;
end

代码 2-3 综合成一个带有同步置位的 D 触发器,其余与 2-1 无异。
// 2-4 时序逻辑,带同步置位和异步复位
reg [1:0] q;
always @ (posedge clk or posedge set or negedge rst_n)
begin
if(!rst_n)
q <= 2'b00;
else if(set)
q <= 2'b11;
else
q <= q + 1'b1;
end
RTL 图:

可以看到多了个与门,代码 2-4 是代码 2-2 和 代码 2-3 的组合结果。
当然咯,这里的综合是指的逻辑综合,而实际上的综合和具体实现与逻辑无关。比如在 FPGA 芯片使用的是查找表LUT,并没有独立的组合逻辑。而仿真器则使用编译方法,仿真器把 verilog 语言编译为 x86 汇编并直接在 CPU 上运行。
好啦,本篇到这里就结束了,下一篇会深入讨论综合工具的一些其他细节。
我的 FPGA 学习历程(15)—— Verilog 的 always 语句综合的更多相关文章
- 我的 FPGA 学习历程(12)—— 电子钟项目准备
初学 FPGA 的时候,我们总是存在很多疑问,比如:xilinx 和 altera 的 FPGA 那种比较好.verilog 语言被如何综合成具体硬件电路.RTL 级电路是什么意思等等.现在我们就不会 ...
- 我的 FPGA 学习历程(04)—— 练习 verilog 硬件描述语言
这篇讲的是使用 verilog 硬件描述语言编写一个 3 - 8 译码器. 3 - 8 译码器是一个简单的组合逻辑,用于实现并转串,其输入输出关系如下: | 输入 | 输出 | -------- ...
- 我的 FPGA 学习历程(01)—— FPGA 基础知识和 Quartus 的安装
高级的嵌入式市场主要分为以下三类:ARM.DSP 和 FPGA. 其中 ARM 是行业内的佼佼者,目前几乎所有的安卓智能手机都使用 ARM 授权的 CPU架构:而 DSP(数字信号处理器) 早年就被大 ...
- 我的 FPGA 学习历程(09)—— 时序逻辑入门
讲到这篇时,组合逻辑就告一段落了,下面是一些总结: 描述组合逻辑时,always 语句中的敏感信号列表中需要列出全部的可能影响输出的变量 描述组合逻辑时,always 语句中的赋值总是使用阻塞赋值符号 ...
- 我的 FPGA 学习历程(05)—— 使用 Modelsim 仿真工具
在第 3 篇中讲到了如何使用图形进行仿真激励输入,图形输入法尽管简单易学,但如若要求复杂的仿真输入激励.较长的仿真时间或是要求打印输出信息乃至输出文件日志则显得不够用了. 本篇以上一篇的 3-8 译码 ...
- 我的 FPGA 学习历程(02)—— 实验:点亮 LED 灯
关于 Quartus 的操作可以使用 Quartus 自带的帮助,帮助中带有全套的操作教程. 中文网络教程链接(链接至 altera中文官网,点击观看) Quartus II 软件设计系列:基础 Qu ...
- 我的 FPGA 学习历程(14)—— PWM 脉冲宽度调制
PWM 是一种调节输出功率的技术(俗称调压),其原理在于改变输出方波的占空比,具体输出见下图: 输出信号为电压值,当负载为恒阻时,上图中的输出功率分别为 25%.50%.75%. 实现方法如下: 设置 ...
- 我的 FPGA 学习历程(07)—— BCD 编码:移位加 3 算法
2-10 进制码,也称为 BCD 码,它的编码方式则是通过一个 4 位二进制来表示一个 10 进制数,部分十进制对应的 BCD 码如下 十进制数 | BCD 码 13 --> 0001_0011 ...
- 我的 FPGA 学习历程(03)—— 使用 Quaruts 自带仿真工具
在上一篇中详细的介绍了怎样创建原理图工程,这篇同样使用原理图工程新建一个多路选择器,目的是学习使用图形输入的仿真工具输入仿真激励. 新建工程,并绘制以下的原理图. 编译项目,会多出一个警告: Crit ...
随机推荐
- 红帽学习记录[RHCE] 防火墙与网络合作
目录 防火墙 基本介绍 firewalld 区域zone 管理firewalld 关于富规则 定义 firewalld操作富规则的命令 语法 常用的示例 网络合作 链路聚合 网络组的文件 网络组命令 ...
- (三十八)golang--json(对切片、map、结构体进行序列化)
JSON(javascript object notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成.key-val JSON是在2001年开始推广的数据格式,目前已 ...
- 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)
欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...
- [Odoo12基础教程]之第一篇-创建Todo应用
声明: 本教程基于 Ruter 老师的 [Odoo基础教程系列] ,Ruter老师教程的链接地址为:Odoo基础教程系列 . 至于为什么已经有了Ruter老师的教程,还要自己再搬移一份呢?是基于一 ...
- 2019-10-16:渗透测试,基础学习,burpsuit学习,爆破的四种方式学习
Burp Suite 是用于攻击web 应用程序的集成平台,包含了许多工具.Burp Suite为这些工具设计了许多接口,以加快攻击应用程序的过程.所有工具都共享一个请求,并能处理对应的HTTP 消息 ...
- 【Luogu P1439】最长公共子序列(LCS)
Luogu P1439 令f[i][j]表示a的前i个元素与b的前j个元素的最长公共子序列 可以得到状态转移方程: if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; d ...
- Java包package之间调用问题-cmd运行窗口编译运行
问题:在使用了java包机制(package)后,编译出现错误:找不到或无法加载主类 xxx 的错误提示信息(各种编译不通过) 先给演示结果: 编译:javac -d classes src/a/He ...
- docker容器访问宿主机的IP——以rocketmq管理工具为例
在宿主机(MacOS系统)上运行了原生的RocketMQ服务,为了方便管理,需要以Docker方式运行RocketMQ的管理工具——rocketmq-console (项目地址:https://git ...
- 教你如何提高 PHP 代码的质量
说实话,在代码质量方面,PHP 的压力非常大.通过阅读本系列文章,您将了解如何提高 PHP 代码的质量. 我们可以将此归咎于许多原因,但这肯定不仅仅是因为 PHP 生态系统缺乏适当的测试工具.在本文中 ...
- NSURLConnection发送GET请求
// ViewController.m // 04-掌握-NSURLConnection发送GET请求 // // Created by xiaomage on 16/2/22. // Copyrig ...