当前位置: 首页 > news >正文

verilog语法实例学习(1)

    本文档中通过verilog实例来学习verilog语法。Verilog是一种硬件描述语言,它具有并发性和时序性。并发性是指不同硬件模块的同时操作,时序性是指信号的赋值或操作在时钟的边沿进行。由于作者本身也是一个初学者,所以尽量用简单明了的例子介绍Verilog语法。

Verilog中的注释

      Verilog代码中的注释和c++语言相同,分为短注释(//)和长注释(/* … */)。短注释通常放在每行代码的后面或上面,用来注释这行代码的功能。长注释一般在module的开始处,用来说明模块的功能。比如下面四位全加器代码中的注释。

/*
  通过实例化全加器模块实现四位加法的功能。
  输入:cin,进位
       x, y 被加数和加数
       s 和
       cout 进位
*/
module adder4(cin, x, y,s,cout);

  input cin;
  input [3:0] x;
  input [3:0] y;

  output [3:0] s;
  output cout;
  wire [3:1] c; 

  fulladd stage0(.cin(cin),.x(x[0]),.y(y[0]),.s(s[0]),.cout(c[1]));
  fulladd stage1(.cin(c[1]),.x(x[1]),.y(y[1]),.s(s[1]),.cout(c[2]));
  fulladd stage2(.cin(c[2]),.x(x[2]),.y(y[2]),.s(s[2]),.cout(c[3]));
  fulladd stage3(.cin(c[3]),.x(x[3]),.y(y[3]),.s(s[3]),.cout(cout));

endmodule

Verilog中的信号

      Verilog中,电路里面的一个信号就代表一个特定类型的线网(net)或变量。这里线网指的两个或更多电路结点的相互连接。

      一个线网或变量的声明格式如下:

      type [range] signal_name{,signal_name};

      方括号中range(范围)是可选的,如果没有指定范围,默认情况下表示该信号是标量,是只有一位的单位信号。大括号中表示允许加入的条目,也就是说一个在一行里面可以声明多个线网或变量。

      范围表示为[Ra:Rb]的形式,它定义了矢量信号的范围。范围[Ra:Rb]可以增大或减小。在任何情况下,Ra都表示一个矢量信号的最高有效位(最左边),Rb表示一个矢量信号的最低有效位(最右边)。Ra和Rb可以是正整数和负整数。

比如:

   wire [7:0] x1,x2;

   wire [3:1] Array;

   reg y1,y2;   //y1和y2没有指定范围,只有一位。

标识符

      在verilog中,线网或变量名字是通过标识符来表示的。标识符是由一些字母,数字,下划线或美元符号组成。但必须注意两点:标识符不能以数字开头,也不能使用verilog中的关键字。Verilog标识符中也可以出现转义字符,比如 \abc,如果用转义字符,则可以用特殊字符,比如\*cd,但是通常写代码过程中,不要用转义字符来定义变量,这种转义字符通常是其它语言用工具翻译成verilog语言时自动插入的。另外注意的一点就是verilog是区分大小写的,m和M是两个不同的变量

合法的标识符:

f, x, x1, x_y, Byte

非法的标识符:

1x, 100, x*y,default(verilog关键字

      Verilog中一些系统任务或函数以$开头,比如$display, $fopen, $monitor等等。Verilog中还定义一些编译指示,以`开头,比如:`timescale 1ns/1ns,定义时间单位和时间精度。

信号的值

Verilog支持单位信号表示的标量(一位信号)或者矢量(多位信号),每个单位信号有四种可能的值:0,1,z(或者Z),x(或者X)。

0, 逻辑值0

1, 逻辑值1,

在正逻辑系统中,逻辑值0表示低电平,逻辑值1表示高电平。负逻辑系统中正好相反。在教程中,我们总是用正逻辑系统。


clip_image002

      我们用阈值电压来表示电平的逻辑值。 在上图中,最低电压为 Vss,表示接地。VDD表示最高电压,表示接电源,通常电源在5v到1v之间。VDD~V1,min之间的范围对应逻辑值1,V0,max~Vss之间的范围对应逻辑值0。典型的V1,min 是60%Vdd,V0,max是40%Vdd

    X, 通常表示多驱动值的冲突,为未初始化的值或者两个反相信号(如0和1)的短接。Verilog中线网和变量的初始值都为X。

clip_image002[6]

Z, 通常表示未驱动的高阻值,此时在电源和地之间没有电流流动。比如在三态门中,E=0,则输出为Z。

clip_image002[8]

Verilog中的数字

信号值如果为标量,则为一位的0,1,x或z。例如:

a = 1’b0; b = 1’b1;

c = x; d = z;

      对于矢量,通常表示为:[size]’[radix]constant, 标量也可以当作size=1的矢量。其中size表示常数的位数,radix为常数的基数。如果没有指定基数,则默认为十进制。Verilog支持的基数有:d(十进制),b(二进制),h(十六进制),o(八进制)。如果定义的位数大于所需要的位数时,通常在前面补0,但是如果最高位是x或z时候,就用x和z来填充。在常量表示中间,可以任意插入下划线,把数字隔开,以方便阅读。可以在基数前面加s(或者S)以表示这是一个有符号数,若未指定一个整数的进制类型,则默认是有符号数,若指定了进制类型,仅当基数前有s,则其为有符号数,否则为无符号数。对于有符号数,如果定义的位数大于所需要的位数时,前面补最高有效位(MSB),如下表中的8’sha9。

下面是一些实例:

数字表示

二进制

注释

reg [31:0] a = 8'sha9

‘11111111111111111111111110101001

8位有符号数,所以进行MSB位扩展,

reg [31:0] b = 4'd5

’00000000000000000000000000000101

4位无符号数,高位补0

reg [31:0] c = 12'h5b_3

‘00000000000000000000010110110011

忽略下划线,12位的无符号数,高位补0

reg [31:0] d = -8'b101

’11111111111111111111111111111011

负数转为补码表示,MSB位扩展到32位

reg [31:0] e= 10'o752

‘00000000000000000000000111101010

8进制无符号数,高位补0

reg [31:0] f = 8'hf

’00000000000000000000000000001111

16进制无符号数,高位补0

reg [31:0] g = 12'hxa

‘00000000000000000000xxxxxxxx1010

左边补x直到12位,然后高位补0

reg [31:0] h = -8'sha9

’00000000000000000000000001010111

补码表示负数,扩展MSB位,

reg [31:0] i = 8'ha9

‘00000000000000000000000010101001

无符号数,高位补0

reg [31:0] j = -4'sha

’00000000000000000000000000000110

补码表示负数,扩展MSB位。

实现这些实例的verilog代码为:

`timescale 1ns/1ns
module verilogdisnum;
  reg [31:0] a = 8'sha9;
  initial $displayb("a=",a);
  reg [31:0] b = 4'd5;
  initial $displayb("b=",b);
  reg [31:0] c = 4'h5b_3;
  initial $displayb("c=",c);
  reg [31:0] d = -8'b101;
  initial $displayb("d=",d);
  reg [31:0] e= 10'o752;
  initial $displayb("e=",e);
  reg [31:0] f = 8'hf;
  initial $displayb("f=",f);
  reg [31:0] g = 12'hxa;
  initial $displayb("g=",g);
  reg [31:0] h = -8'sha9;
  initial $displayb("h=",h);
  reg [31:0] i = 8'ha9;
  initial $displayb("i=",i);
  reg [31:0] j = -4'sha;
  initial  $displayb("j=",j);
endmodule

Verilog中的参数

参数由一个标识符和一个常数组成。比如:

parameter n=4;

parameter S0=2’b00; S1=2’b01;S2=2’b10;S3=2’b11;

      标识符n可以在代码中替换表示数字4的地方,S0则可以替换数值2’b00。参数的主要作用是指定参数化的子电路。比如下面的代码中,可以看到代码通过parameter定义了一个常量n,实例化时候通过addern #(.n(32)) addern_0(…)的形式把32传入到参数n中,从而实现32位的加法操作。另外一种调用参数的方法是用defparam,比如下面的例子:

addern addern_0(…)

defparam addern_0.n=32;

但这种方法是不可综合的,通常只是用在testbench当中

module addern(x, y, s, cout);
  parameter n=8;
  input [n-1:0] x;
  input [n-1:0] y;
  output reg[n-1:0] s;
  output reg cout;
  reg [n:0] c;
  integer k;
  always @(x,y) begin
    c[0] = 1'b0;
	 for(k = 0; k < n; k = k + 1) begin
	   s[k] = x[k]^y[k]^c[k];
		c[k+1] = (x[k]&y[k])|(x[k]&c[k])|(y[k]&c[k]);
	 end
	 cout = c[n];
    end
endmodule
`timescale 1ns/1ns
`define clock_period 20
module addern_tb;
  reg [7:0] x,y;
  wire cout;
  wire [7:0] s;
  reg clk;
  addern #(.n(32)) addern_0(
						.x(x),
						.y(y),
						.s(s),
						.cout(cout)
                  );
  initial clk = 0;
  always #(`clock_period/2) clk = ~clk;
  initial begin
     x = 0;
     repeat(20)
	    #(`clock_period) x = $random;
   end
  initial begin
     y = 0;
     repeat(20)
	    #(`clock_period) y = $random;
   end
  initial begin
     #(`clock_period*20)
	  $stop;
  end
endmodule

转载于:https://www.cnblogs.com/mikewolf2002/p/10183150.html

相关文章:

  • Docker三剑客之docker-machine
  • 正者表达式exec和match
  • Linux操作系统有什么吸引力,在程序员中这么受欢迎!
  • Oracle常用语句
  • Ubuntu Vscode安装
  • wx2tt 微信小程序转头条小程序工具
  • Min_25筛
  • spring-boot切面编程-日志记录
  • 从0到1学C++ 第2篇 认识C++面向过程编程的特点
  • Java01
  • 苹果下调财收预期,致使股价大跌近10%,万亿身家缩水近一半
  • 图像的等距变换,相似变换,仿射变换,射影变换
  • 解决NoclassDefFoundError 打印一个类的java路径
  • 从Lucene到Elasticsearch:从 Lucene 到 ElasticSearch
  • 【文文殿下】ExBSGS
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Electron入门介绍
  • EOS是什么
  • HTML-表单
  • in typeof instanceof ===这些运算符有什么作用
  • Java编程基础24——递归练习
  • js作用域和this的理解
  • Netty源码解析1-Buffer
  • Sass 快速入门教程
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • 初识 webpack
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 免费小说阅读小程序
  • 如何设计一个微型分布式架构?
  • 手写双向链表LinkedList的几个常用功能
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • #{}和${}的区别?
  • #etcd#安装时出错
  • (2)(2.10) LTM telemetry
  • (day6) 319. 灯泡开关
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)原始图像数据和PDF中的图像数据
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Core引入性能分析引导优化
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET文档生成工具ADB使用图文教程
  • @Transactional类内部访问失效原因详解
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [BUG] Authentication Error
  • [CSS]中子元素在父元素中居中
  • [hive小技巧]同一份数据多种处理
  • [Luogu 2816]宋荣子搭积木
  • [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]对象名 'XXX' 无效
  • [NISACTF 2022]sign-ezc++