语句分为:赋值语句、块语句、条件语句、循环语句、结构说明语句、编译预处理语句
1 赋值语句、结构说明语句、阻塞与非阻塞
1.1 赋值语句
1.1.1 连续赋值语句assign
assign语句
用于对wire型变量赋值,是描述组合逻辑最常用的方法之一。
例如assign c=a&b; //a、b可以是wire型变量或寄存器变量,c必须是wire型变量或其他线网型变量。
1.1.2 过程赋值语局“=”和“<=
用于对reg型变量赋值
在过程块中使用过程赋值语句。
1.2 结构说明语句
1.2.1 结构说明语句always
always块包含一个或一个以上的语句(如:过程赋值语句、条件语句和循环语句等),在运行的全过程中,在时钟控制下被反复执行。
时钟有效边沿来了就执行。
在always块中被赋值的只能是寄存器reg型变量。
always块的写法是:always @ (敏感信号表达式)
例如:
always @ (clk) //只要clk发生变化就触发
always @ (posedge clk) //clk上升沿触发
always @ (negedge clk) //clk下降沿触发
always @ (negedge clk1 or posedge clk2) // clk1下降沿触发,clk2上升
沿也触发
always @ (*)该语句所在模块的任何输入信号变化了都触发。
1.2.2 结构说明语句initial
initial语句用于对寄存器变量赋予初值
![在这里插入图片描述](https://img-blog.csdnimg.cn/5a02b9df216f43d7b991b8ab71736fae.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/4d09da43a4ae449dbece1808dbe8b808.png)
1.3 阻塞与非阻塞
阻塞的概念:
在一个块语句中,如果有多条阻塞赋值语句,在前面的赋值语句没有完成之前,后面的语句就不能被执行,就像被阻塞了一样,因此称为阻塞赋值方式。
阻塞(blocking)赋值方式:
赋值符号为=,如 b = a ;
非阻塞的概念:
多条非阻塞赋值在过程块内同时完成赋值操作,多条语句相当于同时执行!
非阻塞(non-blocking)赋值方式:
赋值符号为<=,如 b <= a ;
更多可以见:小梅哥Xilinx FPGA学习笔记9——语法(阻塞与非阻塞赋值)
1.3.1 阻塞的研究
c=b=i_a
![在这里插入图片描述](https://img-blog.csdnimg.cn/50cb3a9cf210477ab95dca3f8880ce73.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/eb132eee366b44e48ddeb0b79ee24880.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/6de1b3bbf67f4543bb8a10b88e45b6a4.png)
1.3.2 非阻塞的研究
c是b的旧值
![在这里插入图片描述](https://img-blog.csdnimg.cn/86d87a33786c4d239f6dc2df0d501068.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/de5aa02d288948f0b040e9073f936696.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/5a39fcbd98324b28a5b9cae3fae21d7b.png)
1.3.3 非阻塞及阻塞的比较
![在这里插入图片描述](https://img-blog.csdnimg.cn/f2fe41d89777491ebdec7970c54d80f6.png)
2 条件语句
条件语句用于always或Initial过程块内部,主要包含if-else语句和case语句。
2.1 条件语句if
if-else语句用于判定所给条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。if-else语句有3种形式。
![在这里插入图片描述](https://img-blog.csdnimg.cn/b4c367d47e4544afa2d172ab8564a5f0.png)
如果语句有多条组成,必须包含在begin和end之内。
3种形式的if语句后面都有表达式,一般为逻辑表达式为关系表达式。当表达式的值为1,按真处理,若为0、x、z,按假处理。
else语句不能单独使用,它是if语句的一部分
![在这里插入图片描述](https://img-blog.csdnimg.cn/50e1d8b91720491abea9909f8559a17b.png)
2.2 case语句
case语句是一种多分支选择语句,if只有两个分支可以选择,但是case可以直接处理多分支语句,这样程序看起来更直观简洁。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d8732e15061844319e54f2ccc6d3e056.png)
case(表达式)
分支表达式: 语句;
分支表达式: 语句;
… …
默认项(default) 语句;
endcase
![在这里插入图片描述](https://img-blog.csdnimg.cn/64538153ee204705a338fdb9c1a9f78c.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/17ac7745756f4a60ae4ad36b1daec29d.png)
case语句的所有表达式的值的位宽必须相等。
在case语句中,分支表达式每一位的值都是确定的(或者为0,或者为1);
在casez语句中,若分支表达式某些位的值为高阻值z,则不考虑对这些位的比较;
在casex语句中,若分支表达式某些位的值为z或不定值x,则不考虑对这些位的比较。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f59ca5a170cc4b8290eb6f6470fd812b.png)
3 循环语句
在Verilog中存在着多种循环语句,用来控制执行语句的执行次数。
在FPGA设计中,循环语句不一定能被综合,多用于在仿真代码生成仿真激励信号
3.1 循环语句forever
forever语句: 连续执行的语句。
格式:forever begin语句块end
forever常用于仿真代码中。
仿真的时间单位,可以在系统中设置,也可以在仿真文件的开始加上:`timescale 1ns / 1ps //时间单位1ns, 精度1ps
仿真程序代码【1】和【2】是等价的,都是产生20个时间单位的方波,占空比50%。
![在这里插入图片描述](https://img-blog.csdnimg.cn/cce53b6efce342c5bb9e6140764362d4.png)
3.2 循环语句repeat
repeat语句: 连续执行n次的语句。
格式:repeat(表达式) begin语句块end
其中 **“表达式”**用于指定循环次数,可以是一个整数、变量或者数值表达式。如果是变量或者数值表达式,其数值只在第一次循环时得到计算,从而得到确定循环次数。
repeat语句也常用于仿真。例如:
repeat (10)
begin
#10 clk=0;
#10 clk=1;
end
3.3 循环语句while
while语句: 执行语句,直至某个条件不满足。
格式:while(表达式) begin语句块end
表达式是循环执行条件表达式,代表了循环体得到继续重复执行时必须满足的条件,通常是一个逻辑表达式。
在每一次执行循环体之前,都需要对这个表达式是否成立进行判断。while 语句在执行时,首先判断循环执行条件表达式是否为真,如果真,执行后面的语句块, 然后再重新判断循环执行条件表达式是否为真,直到条件表达式不为真为止退出循环。
在执行语句中,如果没有改变循环执行条件表达式的值的语句,循环就成为死循环。
![在这里插入图片描述](https://img-blog.csdnimg.cn/75f5623768604ee4ad221efba94145cb.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a59a158aae4a4185a4ccd50b22d9ff97.png)
3.4 循环语句for
for 语句: 三个部分
for(表达式1;表达式2;表达式3)
for(循环变量赋初值;循环执行条件;循环变量增值)。
例如 for(i=0;i<=7;i=i+1)。
如果要让系统能够综合,那么循环的次数一定是固定的。
程序实例实现了统计输入的8位数据in中1的个数,每个时钟上升沿统计一次。
![在这里插入图片描述](https://img-blog.csdnimg.cn/c5448b35a92043c5a72bc6b629e35302.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/4f1f44c27b8c41408e309f9e2e8b26d8.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/57eb1d19c0654438a045baeca73b4ceb.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/dfabc56f1fe441f4a0e8da303ea92536.png)