FPGA-Verilog学习总结
原文链接:https://mp.weixin.qq.com/s/FAY809M1MlzeXjHPtIWdxA一、阻塞赋值和非阻塞赋值问题;
1.1 阻塞赋值,即“=”。用于组合逻辑的设计中,例如:
1)连续赋值语句:
图片
2)在always模块中设计的组合逻辑电路:
图片
1.2 非阻塞赋值,即“<=”。用于时序逻辑设计。例如:
图片
1.3 两者的区别:
a.阻塞赋值先赋值,always块才会结束,即在阻塞赋值过程中不允许其他指令的插入,直到完成赋值为止;
b. 而非阻塞赋值在赋值的过程中可以插入其他指令,在块结束之后才赋值;
导致结果的不同:
a. test1模块得到的结果是当时钟的上升沿到来时b的值为a的值,而c的值也为a的值,因为a的值送给b之后,才实行c=b操作,此时b已经变为a的,所以c也为a的值;
b. test2中的结果为b等于a,而c等于b原来的值,因为在模块结束后才将a值送给b,而c=b操作在模块结束之前就完成了,所以c为b的值。
所以可以看到在相同的环境下,不同的幅值方式产生了很大的差别,所以为了达到设计的要求,避免冒险竞争问题,应按下列要求进行设计:
1)在设计时序电路建模和锁存器建模时,用非阻塞赋值;
2)在电平触发的always块和连续赋值语句设计的组合逻辑电路时,用阻塞赋值;
3)在时钟边沿触发的always块中设计组合和时序逻辑电路时,用非阻塞赋值;
4)不能在同一个always块中同时出现阻塞赋值和非阻塞赋值。
.
.
.
二、同步复位和异步复位的问题
2.1 首先是同步复位,详细如下:
图片
具体为:在always块的条件中不加入复位信号rst,此时只有当clk的上升沿到来时,才能进入always块中实现复位,即与时钟同步,所以称为同步复位。
2.2 其次是异步复位,详细如下:
图片
具体为:在always块的条件中加入复位信号rst,此时不只有当clk的上升沿到来时,才能进入always块中实现复位,rst的下降沿到来时也能实现复位,即可以不与时钟同步,所以称为异步复位。
2.3 各自的优缺点
1)同步复位的优点:
a. 可以实现系统的100%的同步,方便时钟分析;
b. 可以防止复位信号的突变,以为即使复位信号有突变,此时时钟信号的上升沿没有到来,也不能实现复位;
2)同步复位的缺点:
a. 复位信号的有效时间必须大于一个时钟周期才能反映,如果复位信号延时过短就不能实现复位;
b. 在逻辑器件中的所有触发器都是异步复位的,所以在使用同步复位时,在每一个触发器的输入端都需添加一个寄存器,这样就无形中消耗了资源;
3)异步复位的优点:
a. 可以实现全局随时复位,操作简单;
b. 在每个触发器前不需要多余的寄存器,减少资源消耗;
4)异步复位的缺点:
a. 如果复位信号出现尖刺,容易导致异常复位,影响系统正常运作;
所以各有千秋,推荐使用异步复位,因为尖刺并不会容易产生,不必过于担心,而且能够实现随时手动复位,减少资源消耗。
.
.
.
三、状态机的设计流程及其注意事项
3.1 状态机设计步骤
a. 捋清事件的来龙去脉,事件原因即为逻辑输入,结果即为逻辑输出,输入输出的关系即为逻辑关系;
b. 将实际的逻辑关系用逻辑函数表示,然后将函数化简,函数越简单,电路实现就越简单,利用的资源也就越少;
c. 列出状态转换表或状态转换图;
d. 状态编码,即选择gray编码或独热编码,如果FPGA器件的触发器资源丰富,推荐使用独热编码,即使电路的复杂度会增高,但能提高电路的性能;
e. 捋清每一个状态下,相应值的赋值情况,即将某些状态符置高或置低;
f. 捋清状态转换的条件;
g. 选择case语句或if-else语句实现代码描述。
3.2 状态机设计注意事项
a. 在描述多状态转换时,推荐利用case语句实现代码描述,并且添加default选项,让状态机回到初始状态,防止出现锁存状态;
b. 为了能综合出有效地电路,状态机中必须明确的由唯一时钟触发,即同步状态机;
c. 状态机应该有一个同步或异步复位端,推荐使用异步复位端;
d. 在设置编码状态的名称时,要按相应的功能命名,方便代码理解与维护。
.
.
.
四、task和function说明语句
1)任务和函数的不同点:
a. 任务可以调取其它的任务或函数,函数不能调取任务;
b. 任务可以具有自己的仿真时间,但是函数只能和主module的仿真时间相同;
c. 任务可以有任何类型的变量或者没有,但是函数至少有一个输入变量;
d. 任务不返回值,只是执行某操作,而函数有返回值。
2)task的说明
a. 任务的定义:
图片
b. 任务的调用:
直接在需要执行任务中的功能的地方写上任务名即可,如果有端口,把端口写上:
<任务名>(端口1,端口2,…,端口n);
下面是一个具体的例子用来说明怎样在模块的设计中使用任务,使程序容易读懂:
图片
这个例子描述了一个简单的交通灯的时序控制,并且该交通灯有它自己的时钟产生器。
3) function说明语句
函数的目的是返回一个用于表达式的值。
a. 定义函数的语法:
图片
其中<返回值的类型或范围>可以缺省,缺省状态下默认为一位的寄存器类型。例子如下所示:
图片
从上例子中可以看出,函数的返回值就是函数名,函数名同时代表着一个寄存器,此寄存器的类型或范围与定义的<返回值的类型或范围>相同。
b. 函数的调用
函数的调用是通过将函数作为表达式中的操作数来实现的。
其调用格式如下:
<函数名> (<表达式>,<表达式>)
其中函数名作为确认符。
下面这句表达式调用了getaddr函数实现地址高低位拼接功能。
图片
c. 函数的使用规则
除了前面与任务比较时提到的函数规则之外,另添加如下两条:
函数的定义不能包含有任何的时间控制语句,即任何用#、@、或wait来标识的语句。
在函数的定义中必须有一条赋值语句给函数中的一个内部变量(即函数名)赋以函数的结果值。
d. 举例说明
下面的例子中定义了一个可进行阶乘运算的名为fact的函数,该函数返回一个32位的寄存器类型的值,该函数可后向调用自身,并且打印出部分结果值。
图片
页:
[1]