Verilog编程学习2

Posted on 2023-01-15 00:59  _Chapman  阅读(302)  评论(0)    收藏  举报

模块的结构

Verilog里面最基本的设计单元时“模块”(block),这一个概念相当于C里面子函数。一个模块是由两部分组成的,一个时描述接口(输入和输出接口),另外一部分时逻辑功能。
每一个Verilog程序包括四个主要部分:
端口定义、IO口说明、内部信号声明、功能定义。
image
上图,一个模块相当于一个小的子程序。可以单独执行,也可以嵌入其他程序。其中,a、b、c、d是模块的四个端口。这几个端口的声明,可以放在括号里面(就跟C函数里面的输出参数相类似),也可拿出来放到模块的module和enmodule之间的开头部分。

功能的定义

模块都有自己的功能,功能定义的三种方法,分别如下:

1、always语句

描述组合的逻辑或描述组合/时序逻辑。其时间控制可以是边沿或者电平触发。可以是单个信号,也可以是多个信号。一个always语句是否执行,要看后面的敏感信号是否触发。例子如下:
image
always后面需要紧跟@,然后括号里面是多个敏感信号,用or或者and连接。这个相当于C里面的||或者&&(或、且)。当括号里面的信号条件都满足的时候,这一部分代码就会执行,而且是顺序执行,从上往下。
关于敏感信号源的状态:
posedge是上升沿,电平从低到高跳变
negedge是下降沿,电平从高到低跳变

边沿触发always行为被用于描述时序逻辑行为。
如果组合逻辑块输入变量很多,那么编写敏感信号列表容易出错,可以这样写。

image
变成
image
其中,上述的a、b、c、d、e、f、g、h、p、m为电平触发的表示方式。

2、assign语句

描述组合逻辑,例如:
image
如上图所示,不像always语句有时序判断逻辑,这是直接执行的。而且可以理解为是无时无刻都在执行,这个和always的区别是,always需要满足括号的条件才执行。

3、initial语句

在模块中只会执行一次的数据,这个和C里面的static差不多。
image

4、例化实例元件

理解为调用模块,信号可以通过模块端口之间进行传递。例如:
有如下一个子模块:
image
下面一个顶层模块对上述子模块调用:
image

在代码中:
time_count #(
.MAX_NUM (TIME_SHOW)
) u_time_count(
.clk (sys_clk),
.ret_n (sys_rst_n),

.flag (add_flag),
)

例化模块的格式为:
<被例化的模块名字> #() <另外起的模块名字>(被例化模块的输入参数);
这是例化模块必须的步骤。可以看出,被例化的模块就像C里面的一个数据类型。定义一个数据类型,这个数据类型在Verilog里面就是被例化模块的名字,然后再给这个模块输入参数。

通常,用下面的一种格式会更好:
image

赋值语句

分为阻塞赋值非阻塞赋值

阻塞赋值如:b = a;
理解为在一个always块中,后面赋值的语句必须是前面赋值语句执行完成之后从才可以执行。
image
在描述组合逻辑的 always 块中用阻塞赋值 = ,综合成组合逻辑的电路结构;这种电路结构只与输入电平的变化有关。

非阻塞赋值:b <= a;
理解为在一个always块中,赋值符号右边的数值先进行计算,在向左边进行赋值。而且多个赋值语句同时进行。
非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial块和always块等过程块中。
image
在描述时序逻辑的 always 块中用非阻塞赋值 <=,综合成时序逻辑的电路结构;这种电路结构往往与触发沿有关系,只有在触发沿时才可能发生赋值的变化。

注意:在同一个always块中不要既用非阻塞赋值又用阻塞赋值(只可以用其中一种)。且不允许在多个always块中对同一个变量进行赋值!

条件语句

1)if else语句

条件语句必须在过程块中使用。例子如下:
image
使用if else语句必须有else判断条件结尾,否则产生锁存器。else后面可以不填,但必须要有,锁存器会影响时序

注:
和C一样,判断条件可以允许简写。如:
if(a) 等同于 if(a == 1)
if(!a)等同于 if(a != 1)

if语句对表达式的值进行判断,若为0,x,z,则按假处理;若为1,按真处理。

若条件后包含了多个操作,则if和else后面的操作需要用begin和end包含多个语句。if else允许嵌套
image

2)case语句
1、分支表达式的值互不相同;
2、所有表达式的位宽必须相等;不能用 ’bx 来代替 n’bx
例如:
image

3、casez
比较时,不考虑表达式中的高阻值
4、casex
不考虑高阻值z 和 不定值x
例如:
image
上图使用casez,定义了一个8位的寄存器sel,里面的值位1100_0011。第一个判断条件:8'b1100_zzzz表示为,低四位高阻态不用比较,只要高四位符合则认为符合条件。
同理,若上图使用casex,第二判断条件:8'b1100_xxzz表示为,低四位的前面两位不用比较,后面两位需要比较。