【Verilog】三、Verilog高级知识点

文章目录

前言

一、阻塞赋值与非阻塞赋值

1.1、阻塞赋值

1.2、非阻塞赋值

二、always语句和assign语句

三、if_else语句和case语句

四、状态机

4.1、状态机介绍

4.2、状态机分类

4.3、状态机写法 

总结


前言

        前面我们对Verilog的基础知识点进行了介绍,在有了一定语法知识的基础上,我们就可以尝试着去了解一些高级知识点了。本篇文章主要介绍阻塞赋值和非阻塞赋值、always语句和assign语句、if_else语句和case语句、状态机等。


一、阻塞赋值与非阻塞赋值

1.1、阻塞赋值

        阻塞赋值是指在一个always块中,后面语句的赋值操作会受到前面语句的影响。即在同一个always块中,一条阻塞赋值语句如果没有执行结束,那么该语句后面的语句就不能被执行。阻塞赋值用“=”表示,在begin和end之间的语句是顺序执行的,属于串行语句。

如下面代码:

        always @(posedge clk or negedge rst_n)begin

                if(!rst_n)begin

                        a = 1;

                        b = 2;

                        c = 3;

                end

                else begin

                        a = 0;

                        b = a;

                        c = b;

                end

        end

        这一段代码的执行结果为,a、b、c的初始值为1、2、3,当时钟上升沿到来时,将0赋值给a,将a赋值给b,将b赋值给c,由于采用的是阻塞赋值,后面的赋值语句必须等前面赋值结束后才能进行,所以最后的结果为:a = 0; b = 0 , c = 0。

1.2、非阻塞赋值

        非阻塞赋值语句符号采用“<=”表示,它与阻塞赋值不同,在always进程中,当前赋值语句不会阻断后面语句的赋值操作。

      如下面代码:

        always @(posedge clk or negedge rst_n)begin

                if(!rst_n)begin

                        a <= 1;

                        b <= 2;

                        c <= 3;

                end

                else begin

                        a <= 0;

                        b <= a;

                        c <= b;

                end

        end

        这段代码与上面的基本一样,只是把阻塞赋值改为了非阻塞赋值,那么最终执行的结果就大不相同了。运用非阻塞语句赋值,当时钟上升沿到来时,将后面的值之间赋值给前面。上面代码所表达的是:当时钟上升沿到来时,将0赋值给a,将a赋值给b,将b赋值给c,最终的结果为:a = 0 ,b = 1 ,c = 2。这是因为,当时钟上升沿到来时,将0赋值给a,所以a = 0;将a赋值给b,但是此时的a还是为1,因为a和b的赋值时同时进行的,所以b= 1;以此类推,c = 2。

       经过上面的学习,我们知道 阻塞赋值和非阻塞赋值最明显的区别就是阻塞赋值采用“=”表示,非阻塞赋值采用“<=”表示。在设计电路时,always时序逻辑电路中多用非阻塞赋值,always组合逻辑电路中多用阻塞赋值;在仿真电路时,initial块中一般用阻塞赋值。

二、always语句和assign语句

        在Verilog程序设计当中,always语句和assign语句是经常用到的两种语句。其中always语句可分为带时钟的always语句和不带时钟的always语句,带时钟的always语句用来设计时序逻辑电路,这个逻辑语句能够产生寄存器;不带时钟的always语句用来设计组合逻辑电路,其功能和assign语句一样。

        通常我们设计时序逻辑电路时采用带时钟的always语句;设计组合逻辑电路时采用assign语句或者不带时钟的always语句。

三、if_else语句和case语句

        在Verilog程序设计中,if_else语句和case语句都是选择语句,当满足某个条件是,就选择某一样状态,当然这两个语句也是有区别的。

        if_else语句具有优先级,是顺序执行的语句,所以我们在写if_else语句时需要对优先级进行考量,不然就会产生和我们设计不符的结果,并且还不容易发现错误。case语句不具有优先级,是一种并行执行的语句。在实际设计中,一般类别少时用if_else语句,类别多用case语句,if_else语句基本上可以处理所有的复杂判断条件,但是在实际电路中占用的资源较多,所以能用case语句尽量用case语句。

四、状态机

4.1、状态机介绍

        Verilog是一种硬件描述语言,我们知道硬件一般都是并行执行的,但当我们需要顺序执行某些步骤时,如果一种采用很多个if语句进行嵌套,那么代码就会很复杂,也就降低了代码的可读性。但如果采用状态机的思想来进行设计,这个问题就迎刃而解了。

4.2、状态机分类

        状态机也叫有限状态机(简称FSM),是一种在有限个状态之间安装一定规律转换的时序电路,可以认为是组合逻辑和时序逻辑的结合。状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行转移,是协调相关信号动作,完成特定操作的控制中心。状态机按照其输出是否与输入有关可分为摩尔状态机(Moore)和米勒状态机(Mealy)两种。

        Moore型状态机:状态机的输出只取决于当前状态,与输入状态无关。

        Mealy型状态机:状态机的输入不仅与当前状态有关,还与输入状态有关。

 

4.3、状态机写法 

        在Verilog程序设计中,状态机的写法有三种,分别是一段式、两段式和三段式。

        一段式状态机:采用一个always块,将整个状态机写到一个always模块里面,在该always模块内既描述状态转移,又描述状态的输入和输出。一段式状态机写法简单,但是不利于维护和升级,状态扩展麻烦,状态复杂容易出错,不推荐这种写法。

        二段式状态机:采用两个always模块来描述状态机,一个always模块采用同步时序描述状态转移;另一个always模块采用组合逻辑判断状态转移条件,描述状态转移规律即输出。这种写法容易产生竞争冒险现象,产生毛刺,而且不利于时序约束,不利于综合器和布局布线器实现高性能的设计,不推荐这种写法。

        三段式状态机:采用三个always块,一个always块采用同步时序逻辑描述状态转移,一个always块采用组合逻辑判断状态转移条件,状态转移规律,另一个always块描述状态输出。三段式状态机与二段式状态机相比,关键在于根据状态转移规律,在上一状态根据输入条件判断当前状态输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。

        在状态机的写法中,推荐设计者采用三段式写法,这样不仅状态跳转清晰明了,并且有利于状态的修改和升级,也利于综合器和布局布线的设计需求。


总结

        本文总结了一些Verilog语法的高级知识点,但这也是我们在设计Verilog程序时常用的,如果想要了解其中的细节,还得是书上的呀!其中可能有讲的不清楚的地方,表达能力有限,还望大家海涵。

        

猜你喜欢

转载自blog.csdn.net/weixin_62912626/article/details/127863477