数字逻辑实践4->面向硬件电路的设计思维--FPGA设计总述
本文是对实验课上讲解的“面向硬件电路的设计思维”的总结,结合数字逻辑课本,进行提炼和整理。
主要来源是课件与本人整理,部分参考了网络大佬的博客。
本文主要介绍不同于之前软件设计思维的硬件设计思维,从非阻塞赋值、并行、面积速度转换、同步电路设计原则、模块划分设计、if-case对比等方面进行整理。
内容太多,我整理了好几天,在浩如烟海的网络前有点无力,想想是自己的实践不够,有一些问题没有亲身体验;也不能一蹴而就,得久久为功。所以这篇文章就当作一个Verilog学习与FPGA设计的总述性文章,后续继续学习我会加深对这些知识的理解。
00 阻塞赋值和非阻塞赋值
概念
回忆一下课本上的相关内容。
阻塞赋值:
"="
Verilog编译器按照这些语句在always块中的先后顺序依次执行。
如果一个变量通过阻塞赋值语句赋值,则这个新赋的值会在这个block中的后续语句中使用。
相当于串行
非阻塞赋值:
"<="
always块中所有非阻塞赋值的语句在求值时所用的值是最初进入always时各个变量已经具有的值。
换一个角度讲,"<="左侧的被赋值变量,只在always结束时统一被更新。
相当于并行
时序电路实例
阻塞赋值
先来看一看这段代码:
1 module example5_5 (x1, x2, x3, Clock, f, g);
2 input x1, x2, x3, Clock;
3 output reg f, g;
4 always @(posedge Clock)
5 begin
6 f = x1 & x2;
7 g=f | x3;
8 end
9 endmodule
可以看到关键点是g的表达式,由于是阻塞赋值,所以相当于:
g=(x1 & x2) | x3;
综合出的电路如图:
非阻塞赋值
1 module example5_6 (x1, x2, x3, Clock, f, g);
2 input x1, x2, x3, Clock;
3 output reg f, g;
4 always @(posedge Clock)
5 begin
6 f <= x1 & x2;
7 g <= f | x3;
8 end
9 endmodule
这个区别之处就在于这个g,是x3与前一个 f 进行"|"运算。
思考
将阻塞赋值的示例代码中的两个执行语句互换位置,会发生什么情况?
可以料见影响比较大。
可见阻塞赋值描述时序电路有风险。
组合逻辑实例
相反的,如果我们要实现 f = a1a0 + a2a1这样一个函数;
阻塞赋值
1 always @(A)
2 begin
3 f = A[1] & A[0];
4 f=f | (A[2] & A[1]);
5 end
非阻塞赋值
1 always @(A)
2 begin
3 f <= A[1] & A[0];
4 f <= f | (A[2] & A[1]);
5 end
可见这段代码有两个特征;
非阻塞赋值的结果在always结束后才可以看到
多次赋值时,后覆盖前。
这两个特征使得第二个f语句出现问题,因为第二个语句
f <= f | (A[2] & A[1]);
右侧的f的值是不可见的。
总结
对组合逻辑建模采用阻塞赋值
对时序逻辑建模采用非阻塞赋值
用多个always块分别对组合和时序逻辑建模
尽量不要在一个always块里面混合使用阻塞赋值和非阻塞赋值。如果在同一个块即为组合逻辑又为时序逻辑,应使用“非阻塞赋值”
01 程序是并行执行的
这里给的例子没怎么看懂。自己查了一下。
先说结论:
各个always块是并行执行的,
always块和initial块之间是并行执行的,
begin-end块内是顺序执行的,
但是非阻塞赋值(<=)是并行执行的,阻塞赋值(=)是顺序执行的,这条优先。且硬件思想的集中体现就是前面提到过的非阻塞赋值带来的并行执行语句。
再回去看例子:
1 module test ( clk, reset, a, b );
2 input clk;
3 input reset;
4 input [ 3:0 ] a;
5 output [ 3:0 ] b;
6
7 reg [ 3:0 ] tempa1, tempa2, b;
8
9 always @ ( posedge clk ) begin
10 if ( ! reset ) begin
11 tempa1<=0;
12 tempa2<=0;
13 b<=0;
14 end
15 else begin
16 tempa1<= a + 1’b1;
17 tempa2<= tempa1 + 1’b1;
18 b<= tempa2 + 1’b1;
19 end
20 end
21 endmodule
可以料见实现的电路:
下面借鉴了这篇文章
波形图:
可以看到强调的还是上面说过的非阻塞赋值的特点。
02 程序的可综合性
实验任务里总有这么一句:“用可综合的代码......”
什么是可综合性,什么又是不可综合性呢?
下面学习了这篇文章
这篇文章讲的挺多,但是我现在这个RTL级还没搞明白的菜鸟用不到这么多,基本筛选如下:
不可综合的Verilog语句:
initial
只能在test bench中使用,不能综合。
assign 和deassign
不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。
fork join 不可综合,可以使用非块语句达到同样的效果。
这个块是并行执行的,但是不可综合。
敏感列表里同时带有posedge和negedge 如:(现在也碰不到
1 always @(posedge clk or negedge clk)
2 begin
3 ...
4 end
03 面积和速度的转换
这里我们说的面积:设计所占用的FPGA逻辑资源数目,一般用所消耗的触发器和查找表(还没学)来衡量。
速度:是指在芯片上可以稳定运行时能达到的最高频率
两者性能上的调配方法:
模块复用
串并变换
可以看到这种串并转换,用更大的面积(即多个子模块并行),达到高频率的效果。这一点后面还会再提到。
流水线
04 同步电路的设计原则
同步设计的优点:
可以有效避免毛刺的影响,提高设计的可靠性
可以简化时序分析过程
可以减少工作环境对设计的影响
设计原则:
(由于应用还不多,对这些体会还不深刻,简单记录:
单时钟
全局时钟网络的时钟是性能最优,最便于预测的时钟,具有最强的驱动能力
单时钟沿
混合时钟会使时序分析复杂、电路工作频率降低
避免使用门控时钟
即时钟不要与组合逻辑再进行组合,如下:
可能引起毛刺、偏移
在模块内部不要再产生时钟了。
05 模块划分的设计原则
封装复用
这有点像C++的封装。
上一层模块只负责下一层模块的依据(即原材料),而具体行为互不相关。
这样就保证了各个模块的相对独立性和内部结构的合理性,便于维护,也使得相同逻辑可以复用同一模块。
同步时序模块的寄存器划分原则
在设计时,应尽量将模块中的同步时序逻辑输出信号以寄存器的形式送出,以便于综合工具区分时序和组合逻辑;
并且时序输出的寄存器应符合流水线设计思路,能工作在更高的频率,以极大地提高模块吞吐量。
流水线设计思路是什么?
就是将组合逻辑系统地分割,并在各个部分(分级)之间插入寄存器,并暂存中间数据的方法。 目的是将一个大操作分解成若干的小操作,每一步小操作的时间较小,所以能提高频率,各小操作能并行执行,所以能提高数据吞吐率(提高处理速度)。
06 通用代码风格
逻辑复用与逻辑复制
对于我这个初学者来说,逻辑复用和逻辑复制十分相似,了解后就知道确实不同,主要是涉及性能衡量尺度:速度和面积的统筹。
逻辑复用是通过提高工作频率来节省面积的优化方法,经常用于存在多个资源可共享单元的设计中。
PS:相当于为了节省人力,而让一个人干三个人的活。
10MHZ乘法器
两个5MHZ乘法器
逻辑复制——面积换速度
逻辑复用是通过增加面积而改善设计时序的优化方法,经常用于调整信号的扇出。
举例就类似于上面的面积换速度
逻辑结构
链状结构
树状结构
if和case语句的使用原则
If语句指定了一个有优先级的编码逻辑,
而case语句生成的逻辑是并行的,不具有优先级。
这里的if的优先级就引起一些其他问题:
1 always@(in0,in1,in2,in3)
2 begin
3 sel = 2’b00 ;
4 if(in0) sel = 2’b00 ;
5 else if(in1) sel = 2’b01 ;
6 else if(in2) sel = 2’b10 ;
7 else if(in3) sel = 2’b11 ;
8 end
9 //当这里in0和in1都==1时,se1=2'b00而不是2'b01;
10 //这就是if-else的优先逻辑。而case是并行的,没有优先级。
if语句可以包含一系列的表达式;/有时甚至一个else就可以是一个二路选择器。
而case语句比较的是一个公共的控制表达式。整个语句块一起构成了一个多路选择器。
这个很好理解。
通常if-else结构速度较慢,但占用的面积小;
case语句结构速度较快,但占用的面积较大。
嵌套的if语句如果使用不当,就会导致设计的更长延时。
如果想利用if语句来实现那些对延时要求苛刻的路径,应将最高优先级给最迟到达的关键信号。(最小生成树思想)。
有时为了兼顾面积和速度,可以将if和case语句合用。
举例
1 //if-else实现四选一
2 module sdata_if (clk, reset, x, s, y);
3 input clk;
4 input reset;
5 input [3:0] x;
6 input [1:0] s;
7 output y;
8
9 reg y;
10 always@(posedge clk)begin
11 if(!reset)begin
12 y<=0;
13 end
14 else begin
15 if(s==2'b00)
16 y<=x[0];
17 else if (s==2'b01)
18 y<=x[1];
19 else if (s==2'b10)
20 y<=x[2];
21 else
22 y<=x[3];
23 end
24 end
25 endmodule
想象一下是什么电路?
就是一个四选一,需要两位的控制信号,这个控制信号就正好是s。
1 //case语句
2 module sdata_if (clk, reset, x, s, y);
3 input clk;
4 input reset;
5 input [3:0] x;
6 input [1:0] s;
7 output y;
8
9 reg y;
10 always@(posedge clk)begin
11 if(!reset)begin
12 y<=0;
13 end
14 else begin
15 case(s)
16 2'b00: y<=x[0];
17 2'b01: y<=x[1];
18 2'b10: y<=x[2];
19 2'b11: y<=x[3];
20 end
21 end
22 endmodule
23
24
实现电路也是类似上面的电路。
避免意外锁存器
锁存器在课本里学过,是用于存储一位数据的元件,电平触发。
其特点是:锁存器在不锁存数据时,输出随输入变化;但一旦数据锁存时,输入对输出不产生任何影响。
而我们在设计电路时,应该避免无意之间产生这种锁存器,否则会导致一些逻辑上的错误。
引起意外锁存器的原因
翻阅了很多网上的总结。有一些规则比较复杂,考虑到我现在的水平,我只记录对初入门水平够用且好理解的方面。后续继续学习可以深入了解更多。
if……else……结构中缺少else
case结构中的分支没有包含所有情况且没有default语句。
建议
如果使用if语句,最好写上else分支;
如果使用case语句,最好写上default语句。
即使需要锁存器,也通过else分支或default分支来显式说明。而不要利用语言特性触发生成(因为不可控)
内容真的好多,一时间难以完全消化...
上传于2021年11月25日23时
数字逻辑实践4->面向硬件电路的设计思维--FPGA设计总述的更多相关文章
- 数字逻辑实践6-> 从数字逻辑到计算机组成 | 逻辑元件总结与注意事项
00 一些前言 数字逻辑是计算机组成与体系结构的前导课,但是在两者的衔接之间并没有那么流畅,比如对面向硬件电路的设计思路缺乏.这篇总结是在数字逻辑和计组体系结构的衔接阶段进行的. 虽然这篇文是两门课的 ...
- 数字逻辑实践2->Verilog编写规范
来源:数字逻辑与Verilog设计实验课讲解,个人做的笔记与整理. 00 规范的重要性 良好的编程风格有利于减少消耗的硬件资源,提高设计的工作频率 . 提高系统的可移植性和可维护性. 程序的格式化能体 ...
- 数字逻辑实践3->EDA技术与Verilog设计
本文属于EDA技术概述类文章 1 EDA技术及其发展 概念 EDA(Electronic Design Automation),指的是以计算机为工作平台,以EDA软件工具为开发环境,以PLD期间或者A ...
- 数字逻辑实践5->Verilog语法 | wire 与 reg 的选择与特性
问题起因:最初学习数字逻辑设计理论的时候还没有注意到,在实验课上写代码的时候发现了一个问题: 对于源码模块的变量定义,何时定义为reg.何时定义为wire?它们各自又有什么特性和物理意义? 1. wi ...
- FPGA学习笔记(三)—— 数字逻辑设计基础(抽象的艺术)
FPGA设计的是数字逻辑,在开始用HDL设计之前,需要先了解一下基本的数字逻辑设计-- 一门抽象的艺术. 现实世界是一个模拟的世界,有很多模拟量,比如温度,声音······都是模拟信号,通过对模拟信号 ...
- 转载--关于FPGA设计数字信号处理电路的心得
FPGA使用的越来越广泛,除了可用于设计控制电路以为,数字信号处理电路更是FPGA的强项和难点.个人可以说才刚刚入门FPGA设计,也做过一些数字信号处理方面的电路设计,记录下个人心得体会. (一)善用 ...
- 小梅哥FPGA数字逻辑设计教程——基于线性序列机的TLC5620型DAC驱动设计
基于线性序列机的TLC5620型DAC驱动设计 目录 TLC5620型DAC芯片概述: 2 TLC5620型DAC芯片引脚说明: 2 TLC5620型DAC芯片详细介绍: 3 TLC ...
- uTenux\AT91SAM3S4C开发套件———硬件电路介绍
无论写什么嵌入式软件,我们都应该首先对硬件有所了解,这样更有助于我们写出高效精简的程序代码.本次活动我们使用的硬件平台是有悠龙公司提供的uTenux\AT91SAM3S4C开发套件,在悠龙公司的主页可 ...
- 数字逻辑与EDA设计
目录 第一章 数字逻辑基础 1.1数制与码制★★★ 数制 码制 1.2基本及常用的逻辑运算★★ 1.2逻辑函数表示方法★★ 1.3逻辑函数的化简★★★ 1.4常用74HC系列门电路芯片★ 第二章 组合 ...
随机推荐
- 题解 [BJOI2017]开车
题目传送门 题目大意 有\(n\)个汽车和\(n\)个加油站,坐标分别为\(a_{1,2,...,n}\)和\(b_{1,2,...,n}\).每辆汽车会到一个加油站,求出最小移动距离之和.有\(m\ ...
- ls命令剖析
目录 ls命令剖析 资料翻译 SYNOPSIS 使用方式 DESCRIPTION 说明 参数的说明 -l 参数字符的解释 文件权限的解释 FILES 文件夹 实战演练 ls 命令 ls -l 命令 l ...
- Mybatis 一对多延迟加载,并且子查询中与主表字段不对应 (19)
Mybatis 一对多延迟加载,并且子查询中与主表字段不对应应用说明. 实现一对多关联(懒加载),一个教研组对应多个教师,既:教师的教研编号与教研组的教研编号关联,并且教师关联教研组外键与教研组编号 ...
- xpath helper插件安装提示程序包无效
参考链接:https://www.jianshu.com/p/b7d782ef81e0 刚学到爬虫,需要在Chrome浏览器安装xpath helper插件结果一直提示"程序包无效" ...
- SpringBoot小知识点
记录SpringBoot的小知识点 一.在 Spring 上下文刷新之前设置一些自己的环境变量 1.实现 EnvironmentPostProcessor 接口 2.spring.factories ...
- Noip模拟36 2021.8.11
刚题的习惯还是改不了,怎么办??? T1 Dove打扑克 考场上打的动态开点线段树+并查集,考后发现自己像一个傻子,并查集就行.. 这几天恶补数据结构疯了 用树状数组维护后缀和,$siz_i$表示编号 ...
- 大神教零基础入门如何快速高效的学习c语言开发
零基础如果更快更好的入门C语言,如何在枯燥的学习中找到属于自己的兴趣,如果把学习当成一种事务性的那以后的学习将会很难有更深入的进步,如果带着乐趣来完成学习那将越学越有意思这样才会让你有想要更深入学习的 ...
- 跳台阶 牛客网 剑指Offer
跳台阶 牛客网 剑指Offer 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). class Solution: #ru ...
- 表示数值的字符串 牛客网 剑指Offer
表示数值的字符串 牛客网 剑指Offer 题目描述 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2"," ...
- JAVA笔记10__Math类、Random类、Arrays类/日期操作类/对象比较器/对象的克隆/二叉树
/** * Math类.Random类.Arrays类:具体查JAVA手册...... */ public class Main { public static void main(String[] ...