明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 6275|回复: 0

【FPGA至简设计原理与应用】第一篇 第三章硬件描述语言Verilog第5节功能描述-组合逻辑

[复制链接]
发表于 2020-9-7 18:38:52 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本案例的编号为:001500000157,如果有疑问,请按编号在下面贴子查找答案:MDY案例交流【汇总贴】_FPGA-明德扬科教 (mdy-edu.com)
本文为明德扬原创及录用文章,转载请注明出处

大家好,近期我们会连载《FPGA至简设计原理与应用》一书,有兴趣的同学可以学习,也希望大家可以对我们的书提出宝贵的意见和建议。


FPGA至简设计原理与应用》书籍连载索引目录

http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=989


读过的朋友可积极在贴后留言,书籍正式出版时,我们会从留言者中挑选20位幸运读者,幸运读者可获潘老师亲笔签名书籍一本。

注:手机浏览可能格式会乱,建议用电脑端进行浏览。






第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的意思是:当敏感事件的条件满足时,就执行一次“程序语句”。敏感事件每满足一次,就执行“程序语句”一次。
1
  
2
  
3
  
4
  
5
  
6
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行代码。需要强调的是,abc任意一个发生变化一次,2行至5行也只执行一次,不会执行第二次。
此处需要注意,仅仅sel这个信号发生变化是不会执行第2行到5行代码的,通常这并不符合设计者的想法。例如,一般设计者的想法是:当sel0c的结果是a+b;当sel不为0c的结果是a+d。但如果触发条件没有发生改变,虽然sel01,但此时c的结果仍是a+b。因此,这并不是一个规范的设计思维。

    因此,按照设计者的想法重新对代码进行设计:当信号a或者信号b或者信号d或者信号sel发生变化时,就执行2行至5行。这样就可以确保sel信号值为0时,c的结果一定为a+b,当sel不为0时,c的结果一定是a+d。因此要在敏感列表中加入sel,其代码如下所示。
1
  
2
  
3
  
4
  
5
  
6
always   @(a or b or d or sel)begin
  
     if(sel==0)
  
         c = a + b;
  
     else
  
         c = a + d;
  
end

    当敏感信号非常多时很容易就会把敏感信号遗漏,为避免这种情况可以用“*”来代替。这个“*”是指“程序语句”中所有的条件信号,即abdsel(不包括c),笔者也推荐这种写法,其具体代码如下所示。

1
  
2
  
3
  
4
  
5
  
6
always   @(*)begin
  
     if(sel==0)
  
         c = a + b;
  
     else
  
         c = a + d;
  
end
   
    这种条件信号变化结果立即变化的always语句被称为“组合逻辑”。

1
  
2
  
3
  
4
  
5
  
6
always   @(posedge clk)begin
  
     if(sel==0)
  
         c <= a + b;
  
     else
  
         c <= a + d;
  
end

    上述代码敏感列表是“posedge clk”,其中posedge表示上升沿。也就是说,当clk0变成1的瞬间执行一次程序代码,即第25行,其他时刻c的值保持不变。要特别强调的是:如果clk没有由0变成1,那么即使abdsel发生变化,c的值也是不变的。

1
  
2
  
3
  
4
  
5
  
6
always   @(negedge clk)begin
  
     if(sel==0)
  
         c <= a + b;
  
     else
  
         c <= a + d;
  
end
   
    可以看到上述代码的敏感列表是“negedge clk”,其中negedge表示下降沿。也就是说,当clk1变成0的瞬间执行一次程序代码,即第25行,其他时刻c的值保持不变。要特别强调的是,如果clk没有由1变成0,那么即使abdsel发生变化,c的值也是不变的。

1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
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”,也就是说,当clk0变成1的瞬间,或者rst_n1变化0的瞬间,执行一次程序代码,即第28行,其他时刻c的值保持不变。

    这种信号边沿触发,即信号上升沿或者下降沿才变化的always,被称为“时序逻辑”,此时信号clk是时钟。注意:识别信号是不是时钟不是看名称,而是看这个信号放在哪里,只有放在敏感列表并且是边沿触发的才是时钟。而信号rst_n是复位信号,同样也不是看名字来判断,而是放在敏感列表中且同样边沿触发,更关键的是“程序语句”首先判断了rst_n的值,这表示rst_n优先级最高,一般都是用于复位。

设计时需要注意以下几点:
1、组合逻辑的always 语句中敏感变量必须写全,或者用“*”代替。
2、组合逻辑器件的赋值采用阻塞赋值“=,时序逻辑器件的赋值语句采用非阻塞赋值“<=”,具体原因见“阻塞赋值和非阻塞赋值”一节内容。



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号 )

GMT+8, 2024-4-27 07:51 , Processed in 0.051087 second(s), 21 queries .

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表