Verilog基础学习二


文章目录

  • Verilog基础学习二
  • 一、always 块
    • 1.阻塞性赋值和非阻塞性赋值
  • 二、条件语句
    • 1.if 语句 基本用法
    • 2.避免引入锁存器
    • 3.case 语句
    • 4.casez 语句
  • 三、归约运算符(Reduction Operators)
  • 四、for循环
    • Problem : Combinational for-loop: 255-bit population count
    • Problem : Generate for-loop: 100-bit binary adder 2
    • 五、Generate 块
    • Problem : Generate for-loop: 100-digit BCD adder
  • 总结

一、always 块

我们知道数字电路是由导线连接的逻辑门组成,因此任何电路都可以表示为moduleassign语句的某种组合。但是,有时候这不是描述电路最简便的方法。过程块(比如always块)提供了一种用于替代assign语句描述电路的方法。

有两种always块是可以综合出电路硬件的:

综合逻辑:always @(*)
时序逻辑:always @(posedge clk)

1.阻塞性赋值和非阻塞性赋值

在Verilog中有以下三种赋值方法:

连续赋值(assign x=y;):不能在过程块内使用;
过程阻塞性赋值(x=y;):只能在过程块中使用;
过程费阻塞性复制(x<=y):只能在过程块内使用。

在组合always块中,使用阻塞性赋值。在时序always块中,使用非阻塞性赋值。具体为什么对设计硬件用处不大,还需要理解Verilog模拟器如何跟踪事件(译者注:的确是这样,记住组合用阻塞性,时序用非阻塞性就可以了)。不遵循此规则会导致极难发现非确定性错误,并且在仿真和综合出来的硬件之间存在差异。

示例代码如下:

module top_module(input clk,input a,input b,output wire out_assign,output reg out_always_comb,output reg out_always_ff   );assign out_assign = a ^ b;always@(*) out_always_comb = a ^ b;always@(posedge clk) out_always_ff <= a ^ b;endmodule

二、条件语句

1.if 语句 基本用法

基本if语句:

always @(*) beginif (condition) beginout = x;endelse beginout = y;end
end

条件(三元)运算符:

assign out = (condition) ? x : y;condition ? if_true : if_false

2.避免引入锁存器

组合电路输出必须在所有输入的情况下都有值。这意味着必须需要else子句或着输出默认值。

3.case 语句

Verilog中的case语句几乎等同于if-else if-else序列,它将一个表达式与其他表达式列表进行比较。它的语法和功能与C语言中的switch语句稍有不同:

always @(*) begin     // This is a combinational circuitcase (in)1'b1: begin out = 1'b1;  // begin-end if >1 statementend1'b0:    out = 1'b0;default: out = 1'bx;endcase
end

1、case语句以case开头,每个case项以冒号结束。而switch语句没有。

2、每个case项只执行一个语句。 *这样就不需要C语言中break来跳出switch。*但这也意味着如果您需要多个语句,则必须使用begin … end。

3、case项允许重复和部分重叠,执行程序匹配到的第一个,而C语言不允许重复的case项目

4.casez 语句

如果case语句中的case项与某些输入无关,就可以减少列出的case项。这就是casez的用途:它在比较中将具有值z的位视为无关项(即输入01都会匹配到)。

还有一个类似的casex,将输入的x和z都视为无关。不认为casex比casez有什么特别的好处。
(作者个人感觉没必要用casex,z和x状态的问题涉及电路的基本知识)
符号"?" 是z的同义词,所以2’bz0与2’b?0相同。

always @(*) begincasez (in[3:0])4'bzzz1: out = 0;   // in[3:1]输入什么都可以4'bzz1z: out = 1;4'bz1zz: out = 2;4'b1zzz: out = 3;default: out = 0;endcase
end

同时为避免生成了不必要的锁存器,必须在所有条件下为所有的输出赋值。这可能会多打很多字,使你的代码变得冗长。 一个简单的方法是在case语句之前为输出分配一个“默认值”

除非case语句覆盖赋值,否则这种代码样式可确保在所有可能的情况下输出0。 这也意味着case的default项变得不必要。

提醒:always@(*)综合器会生成一个组合电路,其行为与代码描述的相同。硬件不会按顺序“执行”代码。

三、归约运算符(Reduction Operators)

归约运算符(Reduction Operators)可以对向量的每一位位进行AND,OR和XOR,产生一位输出:

&a [3:0] // AND:a[3]&a[2]&a[1]&a [0]相当于(a[3:0]== 4'hf)
|b [3:0] // OR: b[3]|b[2]|b[1]|b [0]相当于(b[3:0]!= 4'h0)
^c [2:0] // XOR:c[2]^c[1]^c[0]

四、for循环

for循环(组合always块或者generate块)在处理重复动作的时候很有用。

模块实例化时必须使用generate块

 always@(*)beginfor (int i=0;i<=99;i=i+1)beginout[i]=in[99-i];endend

Problem : Combinational for-loop: 255-bit population count

设计电路来计算输入矢量中 ’1‘ 的个数,题目要求建立一个255bit输入的矢量来判断输入中 ’1‘ 的个数。

module top_module( input [254:0] in,output [7:0] out );integer i;always @ (*)beginout = 8'b0000_0000;     //**为了后面的计数累加,此处先初始化为0.**for (i=0; i<255; i++)beginif(in[i] == 1'b1)out = out + 1'b1;elseout = out + 1'b0;endend
endmodule
  • 循环里面的变量一定要初始化

Problem : Generate for-loop: 100-bit binary adder 2

通过实例化100个全加器来实现一个100bit的二进制加法器。该加法器有两个100bit的输入和cin,输出为sum与cout。为了鼓励大家使用实例化来完成电路设计,我们同时需要输出每个全加器的cout。
故cout[99]标志着全加器的最终进位。

  • ​ 有好多加法器需要实例化,可采用实例化数组或generate语句来实现。

​ 考虑到for循环中只有cin与cout是变化的,每次计算中cout是本次计算的输出,也是下次计算的输入(cout就是下次计算的cin)。故我们先计算出cout[0]sum[0]

assign cout[0] = a[0] & b[0] | a[0] & cin | b[0] & cin;
assign sum[0]  = a[0] ^ b[0] ^ cin;
//一定要记得赋初值,然后再开始循环

代码如下

module top_module( input [99:0] a, b,input cin,output [99:0] cout,output [99:0] sum );integer i;always @(*) begin cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin;sum[0] = a[0] ^ b[0] ^ cin;for(i=1;i<100;i++) beginsum[i] = a[i] ^ b[i] ^ cout[i-1];cout[i] = a[i]&b[i] | a[i]&cout[i-1] | b[i]&cout[i-1];endend
endmodule

五、Generate 块

什么是generate语句?

​ 生成语句可以动态的生成verilog代码,当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者根据参数的定义来确定程序中是否应该包含某段Verilog代码的时候,使用生成语句能大大简化程序的编写过程。

​ 使用关键字generateendgenerate来指定范围。generate语句有generate-for、generate-if、generate-case三种语句,本题中我们使用generate-for语句。

​ generate-for语句:

(1) 必须有genvar关键字定义for语句的变量。

(2)for语句的内容必须加begin和end**(即使就一句)**。

(3)for语句必须有个名字

//创建一个2进制转换器Module gray2bin
#(parameter SIZE = 8)
(input [SIZE-1:0] gray,output [SIZE-1:0] bin
)Genvar gi;  //在generate语句中采用genvar声明generate for (gi=0; gi<SIZE; gi=gi+1) begin : genbit    //for语句必须有名字assign bin[i] = ^gray[SIZE-1:gi];endendgenerate
endmodule

Problem : Generate for-loop: 100-digit BCD adder

​ 本题已经提供了一个名为bcd_fadd的BCD一位全加器,他会添加两个BCD码和一个cin,并产生一个cout和sum。
每个bcd_fadd都是含有两个四位的输入(a,b),一个四位的输出(sum)

module bcd_fadd {input [3:0] a,input [3:0] b,input     cin,output   cout,output [3:0] sum );

我们需要实例化100个bcd_fadd来实现100位的BCD进位加法器。该加法器应包含两个100bit的BCD码(包含在400bit的矢量中)和一个cin,
输出产生sum 和 cout。

module top_module( input [399:0] a, b,input cin,output cout,output [399:0] sum );wire [399:0] cout_temp;genvar i;bcd_fadd inst1_bcd_fadd (.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(cout_temp[0]),.sum(sum[3:0]));//与上题同理,还是先计算cout[0],我声明一个wire型的cout_temp来存放每次计算后cout的值。//类似矢量运算中赋初值,实例的初始化也是必不可少的generatefor(i=4; i<400; i=i+4)begin: bcdbcd_fadd inst_bcd_fadd(.a(a[i+3:i]), .b(b[i+3:i]), .cin(cout_temp[i-4]), //上次计算输出的cout.cout(cout_temp[i]), //本次计算输出的cout,在下次计算中变为cin.sum(sum[i+3:i]));endendgenerate assign cout = cout_temp[396];   endmodule

总结

本次学习了always 块的用法,包含里面的if、case、casez、for语句的具体用法;学习了归约运算符(Reduction Operators)的操作,简化打字量;最后学习了Generate 块的用法,今后在实践中具体操作会有更深刻的理解。

Verilog基础学习二相关推荐

  1. mysql用创建的用户登陆并修改表格_MySQL 基础学习二:创建一个用户表,并增删改查...

    MySQL 基础学习二:创建一个用户表,并 增删改查 提示:MySQL 命令建议都用大写,因为小写运行时,还是翻译成大写的. 第一步,创建一个用户表 1,打开控制台,进入数据库 C:\Users\Ad ...

  2. 大数据基础学习二:在VMware虚拟机上安装Ubuntu完整步骤及需要注意的问题(以VMware Workstation 15.1.0 Pro和Ubuntu18.04.3优麒麟版为例)

    大数据基础学习二:在VMware虚拟机上安装Ubuntu完整步骤及需要注意的问题 (以VMware Workstation 15.1.0 Pro for Windows和Ubuntu18.04.3优麒 ...

  3. python pyramid基础学习二

    python pyramid基础学习二 1.前言 前面我们使用了基础命令创建pyramid项目,并运行了Hello word,万事开头难,我们知道了开发pyramid项目需要一个env文件夹,里面包 ...

  4. Verilog基础学习三

    文章目录 一.基础门电路(Basic Gate) 1.gate 2.真值表 3.关于电路设计思路 4.门电路与向量 二.多路选择器(multiplexer) 1. 2-to-1 multiplexer ...

  5. 【Java进阶营】JAVA多线程基础学习二:synchronized

    本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题,没错就是使用synchronized. 一.如何解决线程安全问题? 一般 ...

  6. Java基础学习(二十七)之IO流

    1. File 1.1 File类概述和构造方法(myFile中的com.itheima_01中的FileDemo01) File:它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对 ...

  7. 19-10-29-C++基础学习二

    上一篇对基础部分的编译流程,输入输出,控制结构,进行了介绍,这篇主要是对里面的变量以及基本类型,标准库,类的简介 进行相关的总结: 变量: ​ · 什么是变量? ​ 变量提供了程序可以操作的有名字的存 ...

  8. 音频基础学习二——声音的波形

    文章目录 前言 一.声音的基础波形 1.正弦波 2.三角波 3.锯齿波 4.方波 二.正弦波 1.什么是正弦 2.什么是正弦波和正弦曲线 三.正弦波与声音 1.角频率 2.基波和谐波 基波: 谐波: ...

  9. Hibernate基础学习(二)—Hibernate相关API介绍

    一.Hibernate的核心接口 所有的Hibernate应用中都会访问Hibernate的5个核心接口. (1)Configuration接口: 配置Hibernate,启动Hibernate,创建 ...

最新文章

  1. 良心直播!看完你的Python入门基础就妥了!
  2. 自定义异常类: 运行期间跟编译期间的区别
  3. rabbitmq的整体架构一览
  4. Windows Server 2016-活动目录NTP时间同步
  5. 隔空操作之简单的模拟三种行为
  6. 读书笔记:黑客与画家
  7. 用扫地机器人楼下吵吗_扫地机器人到底好不好用?说说我两年的使用体验!
  8. 基于注解风格的Spring-MVC的拦截器
  9. 2.1)深度学习笔记:深度学习的实践层面
  10. C++ 的异常处理解答
  11. 用Binary Viewer查看H264文件中的每一帧
  12. 范德波振子的李雅普诺夫指数
  13. 常见系统中文字体的英文名
  14. 《了不起的我》读后感
  15. HTML5中weight属性的作用,css font-weight属性怎么用
  16. 企鹅的java游戏_那只小企鹅终究要和我们告别了,腾讯又两款游戏宣布停运
  17. TOP公链主网技术:多层扩容和多层分片
  18. turtle画了一个皮卡丘
  19. vim编辑器的简单使用(参考别人文章的学习笔记)
  20. 花了4000多的钱,领导让我去开8000多元的发票,我该怎么办??

热门文章

  1. 坦克世界服务器系统不更新失败怎么办,win7系统下坦克世界自动更新失败如何解决...
  2. U盘插入电脑提示需要格式化
  3. JAVA之对象的克隆
  4. Hyperledger Fabric 通道配置文件和容器环境变量详解
  5. linux原生系统_Linux的概述
  6. 对于Windows,GB18030是不可用的
  7. 硬盘装win10系统教程|不需要任何工具
  8. esplise自定义快捷代码补全_Ecplise更便捷的自动补全功能设置及改良
  9. 雇员与雇主的关系之满意度曲线
  10. 【每日新闻】看清小米生态链,再说它值多少钱 | 工信部:二月份查处“黑广播”违法犯罪案件206起