Verilog语法总结

Verilog HDL语法总结

  1. 逻辑 0:表示低电平,也就是对应我们电路的GND;
    逻辑 1:表示高电平,也就是对应我们电路的VCC;
    逻辑 X:表示未知,有可能是高电平,也有可能是低电平;
    逻辑 Z:表示高阻态,外部没有激励信号是一个悬空状态。
  2. Verilog的标识符可以是任意一组字母、数字、 $和_(下划线)符号的组合,但标识符的第一个字符必须是字母或者下划线。另外,标识符是区分大小写的。(采用一些前缀或后缀,比如:时钟采用clk前缀: clk_50m, clk_cpu;低电平采用_n后缀: enable_n;统一缩写,如全局复位信号rst;参数统一采用大写,如定义参数使用SIZE)
  3. 二进制:4’b0101;十进制:4’d2;十六进制:4’ha。当代码中没有指定数字的位宽与进制时,默认为32位的十进制,比如100,实际上表示的值为32’d100。
  4. 在Verilog语法中,主要有三大类数据类型,即寄存器类型、线网类型和参数类型。真正在数字电路中起作用的数据类型应该是寄存器类型和线网类型。
    寄存器类型表示一个抽象的数据存储单元,它只能在always语句和initial语句中被赋值,并且它的值从一个赋值到另一个赋值过程中被保存下来。如果该过程语句描述的是时序逻辑,即always语句带有时钟信号,则该寄存器变量对应为寄存器;如果该过程语句描述的是组合逻辑, 即always语句不带有时钟信号,则该寄存器变量对应为硬件连线;寄存器类型的缺省值是x(未知状态)。
    线网表示Verilog结构化元件间的物理连线。它的值由驱动元件的值决定,例如连续赋值或门的输出。如果没有驱动元件连接到线网,线网的缺省值为z(高阻态) 。
    参数其实就是一个常量,常被用于定义状态机的状态、数据位宽和延迟大小等,由于它可以在编译时修改参数的值,因此它又常被用于一些参数可调的模块中,使用户在实例化模块时,可以根据需要配置参数。在定义参数时,我们可以一次定义多个参数,参数与参数之间需要用逗号隔开。这里我们需要注意的是参数的定义是局部的,只在当前模块中有效。将parameter定义放在紧跟着module的输入输出定义之后。
reg [31:0] delay_cnt; //延时计数器
reg        key_flag ; //按键标志

wire       data_en;   //数据使能信号
wire [7:0] data ;     //数据

parameter DATA_WIDTH = 8; //数据位宽为8位
  1. 算术运算符:常用的算术运算符主要包括加减乘除和模除(模除运算也叫取余运算)。Verilog实现乘除比较浪费组合逻辑资源,尤其是除法。一般2的指数次幂的乘除法使用移位运算来完成运算,详情可以看移位运算符章节。非2的指数次幂的乘除法一般是调用现成的IP。
  2. 逻辑运算符:!,&&,||
    位运算符:~,&,|,^
  3. 拼接运算符:{},例{a,b}:将a和b拼接起来, 作为一个新信号。
  4. 关键字:
    always 产生reg信号语句的关键字;
    assign 产生wire信号语句的关键字;
    :wire信号定义,wire信号就是硬件连线,比如此处的counter_en,代表计数到最大值时产生高电平使能,本质上是一个硬件连线,其实代表的是一些计数器/寄存器做逻辑判断的结果。
parameter WIDTH = 25 ;
parameter COUNT_MAX = 25_000_000;
reg [WIDTH-1:0] counter ;
wire counter_en ;
assign counter_en = (counter == (COUNT_MAX - 1'b1)) ? 1'b1 : 1'b0;
  1. 阻塞赋值,顾名思义,即在一个always块中,后面的语句会受到前语句的影响,具体来说,在同一个always中,一条阻塞赋值语句如果没有执行结束,那么该语句后面的语句就不能被执行,即被“阻塞” 。也就是说always块内的语句是一种顺序关系,这里和C语言很类似。符号“=”用于阻塞的赋值(如:b = a) ,阻塞赋值“=”在begin和end之间的语句是顺序执行,属于串行语句。
  2. 非阻塞赋值,符号“<=”用于非阻塞赋值(如:b <= a),非阻塞赋值是由时钟节拍决定,在时钟上升到来时,执行赋值语句右边,然后将begin-end之间的所有赋值语句同时赋值到赋值语句的左边,注意:是begin—end之间的所有语句,一起执行,且一个时钟只执行一次, 属于并行执行语句。
  3. 在描述组合逻辑电路的时候,使用阻塞赋值,比如assign赋值语句和不带时钟的always赋值语句,这种电路结构只与输入电平的变化有关系,代码如下:
assign data = (data_en == 1'b1) ? 8'd255 : 8'd0;

always @(*) begin
	if (en) begin
		a = a0;
		b = b0;
	end
	else begin
		a = a1;
		b = b1;
	end
end
  1. assign语句和always语句是Verilog中的两个基本语句, 这两个都是经常使用的语句。
    assign语句使用时不能带时钟。
    always语句可以带时钟, 也可以不带时钟。 在always不带时钟时,逻辑功能和assign完全一致,都是只产生组合逻辑。且虽然产生的信号定义还是reg类型,但是该语句产生的还是组合逻辑。
    比较简单的组合逻辑推荐使用assign语句,比较复杂的组合逻辑推荐使用always语句。
  2. latch是指锁存器,是一种对脉冲电平敏感的存储单元电路。 锁存器和寄存器都是基本存储单元锁存器是电平触发的存储器, 寄存器是边沿触发的存储器。两者的基本功能是一样的,都可以存储数据。锁存器是组合逻辑产生的, 而寄存器是在时序电路中使用,由时钟触发产生的。
    latch的主要危害是会产生毛刺(glitch),这种毛刺对下一级电路是很危险的。并且其隐蔽性很强,不易查出。因此,在设计中,应尽量避免latch的使用。代码里面出现latch的两个原因是在组合逻辑中,if或者case语句不完整的描述, 比如if缺少else分支,case缺少default分支,导致代码在综合过程中出现了latch。解决办法就是if必须带else分支,case必须带default分支。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值