马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
第5节 功能描述-组合逻辑
本文档编号:001100000061
需要看对应的视频,请点击视频编号:001100000053
1. 本节主要进行组合逻辑的介绍,包括:程序语句(assign语句、always语句),数字进制(二进制、不定态、高阻态),算数运算符(加、减、乘、除运算符),逻辑运算符(逻辑与、或、非运算符),按位逻辑运算符(单目按位与、或、非运算符,双目按位与、或、异或运算符),关系运算符,移位运算符(左移、右移运算符),条件运算符(三目运算符、if语句、case语句、选择语句等),拼接运算符;
2. ALTERA和VIVADO文档
5.1 程序语句
5.1.1assign语句
assign语句是连续赋值语句,一般是将一个变量的值不间断地赋值给另一变量,两个变量之间就类似于被导线连在了一起,习惯上当做连线用。assign语句的基本格式是: assign a = b (逻辑运算符)c …; assign语句的功能属于组合逻辑的范畴,应用范围可以概括为一下几点: (1)持续赋值; (2)连线; (3)对wire型变量赋值,wire是线网,相当于实际的连接线,如果要用assign直接连接,就用wire型变量,wire型变量的值随时发生变化。 需要说明的是,多条assign连续赋值语句之间互相独立、并行执行。
5.1.2always语句
always 语句是条件循环语句,执行机制是通过对一个称为敏感变量表的事件驱动来实现的,下面会具体讲到。always 语句的基本格式是: always @(敏感事件)begin 程序语句 end always是“一直、总是”的意思,@后面跟着事件。整个always的意思是:当敏感事件的条件满足时,就执行一次“程序语句”。敏感事件每满足一次,就执行“程序语句”一次。 | always @(a or b or d)begin if(sel==0) c = a + b; else c = a + d; end |
这段程序的意思是:当信号a或者信号b或者信号d发生变化时,就执行一次下面语句。在执行该段语句时,首先判断信号sel是否为0,如果为0,则执行第3行代码。如果sel不为0,则执行第5行代码。需要强调的是,a、b、c任意一个发生变化一次,2行至5行也只执行一次,不会执行第二次。 此处需要注意,仅仅sel这个信号发生变化是不会执行第2行到5行代码的,通常这并不符合设计者的想法。例如,一般设计者的想法是:当sel为0时c的结果是a+b;当sel不为0时c的结果是a+d。但如果触发条件没有发生改变,虽然sel由0变1,但此时c的结果仍是a+b。因此,这并不是一个规范的设计思维。
因此,按照设计者的想法重新对代码进行设计:当信号a或者信号b或者信号d或者信号sel发生变化时,就执行2行至5行。这样就可以确保sel信号值为0时,c的结果一定为a+b,当sel不为0时,c的结果一定是a+d。因此要在敏感列表中加入sel,其代码如下所示。 | always @(a or b or d or sel)begin if(sel==0) c = a + b; else c = a + d; end |
当敏感信号非常多时很容易就会把敏感信号遗漏,为避免这种情况可以用“*”来代替。这个“*”是指“程序语句”中所有的条件信号,即a、b、d、sel(不包括c),笔者也推荐这种写法,其具体代码如下所示。
| always @(*)begin if(sel==0) c = a + b; else c = a + d; end |
这种条件信号变化结果立即变化的always语句被称为“组合逻辑”。
| always @(posedge clk)begin if(sel==0) c <= a + b; else c <= a + d; end |
上述代码敏感列表是“posedge clk”,其中posedge表示上升沿。也就是说,当clk由0变成1的瞬间执行一次程序代码,即第2至5行,其他时刻c的值保持不变。要特别强调的是:如果clk没有由0变成1,那么即使a、b、d、sel发生变化,c的值也是不变的。
| always @(negedge clk)begin if(sel==0) c <= a + b; else c <= a + d; end |
可以看到上述代码的敏感列表是“negedge clk”,其中negedge表示下降沿。也就是说,当clk由1变成0的瞬间执行一次程序代码,即第2至5行,其他时刻c的值保持不变。要特别强调的是,如果clk没有由1变成0,那么即使a、b、d、sel发生变化,c的值也是不变的。
| always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin c <= 0; end else if(sel==0) c <= a + b; else c <= a + d; end |
上述代码的敏感列表是“posedge clk or negedge rst_n”,也就是说,当clk由0变成1的瞬间,或者rst_n由1变化0的瞬间,执行一次程序代码,即第2至8行,其他时刻c的值保持不变。
这种信号边沿触发,即信号上升沿或者下降沿才变化的always,被称为“时序逻辑”,此时信号clk是时钟。注意:识别信号是不是时钟不是看名称,而是看这个信号放在哪里,只有放在敏感列表并且是边沿触发的才是时钟。而信号rst_n是复位信号,同样也不是看名字来判断,而是放在敏感列表中且同样边沿触发,更关键的是“程序语句”首先判断了rst_n的值,这表示rst_n优先级最高,一般都是用于复位。
设计时需要注意以下几点: 1、组合逻辑的always 语句中敏感变量必须写全,或者用“*”代替。 2、组合逻辑器件的赋值采用阻塞赋值“=,时序逻辑器件的赋值语句采用非阻塞赋值“<=”,具体原因见“阻塞赋值和非阻塞赋值”一节内容。
|