Verilog语法

目录

  • Verilog语法
    • 一、Verilog基础知识
      • 逻辑值
      • 数字进制
      • 标识符
      • 数据类型
        • 寄存器类型
        • 线网类型
        • 参数类型
      • 运算符
    • 二、Verilog程序框架
      • Verilog注释
      • Verilog关键字
      • Verilog程序框架
        • 模块调用、例化——模块化设计
    • 三、Verilog高级知识点
      • 结构语句
        • initial与always
      • 赋值语句
        • 阻塞赋值(Blocking)
        • 非阻塞赋值(Non-Blocking)
          • 总结
          • assign 和 always 区别
      • 条件语句
        • if_else语句:
        • case语句:
        • latch锁存器
    • 四、Verilog状态机FSM
      • 状态机FSM概念
      • 状态机模型
        • Mealy状态机(输出=输入+之前状态)
        • Moore 状态机(输出=之前状态)
      • 状态机设计
        • 1.状态空间定义
        • 2.状态跳转(时序逻辑)
        • 3.下一个状态的判断(组合逻辑)
        • 4.各个状态下的动作(组合逻辑)
        • 总结

一、Verilog基础知识

逻辑值

0、1、X(未知)、Z(高阻态)

数字进制

二进制:4’b0101 表示 4 位二进制数字 0101;
十进制:4’d2 表示 4 位十进制数字 2(二进制 0010);
十六进制:4’ha 表示 4 位十六进制数字 a(二进制 1010)
当代码中没有指定数字的位宽与进制时,默认为 32 位的十进制,比如 100,实际上表示的值为 32’d100。

标识符

用于定义模块名,端口名,信号名,由字母、数字、$和_(下划线)组成,第一个字符必须是字母或者下划线,区分大小写。
不建议大小写混合使用,普通内部信号建议全部小写,参数定义建议大写。
采用一些前缀或后缀,比如:时钟采用 clk 前缀:clk_50m,clk_cpu;低电平采用_n 缀:enable_n;

数据类型

寄存器类型、线网类型和参数类型。

寄存器类型

是一个数据存储单元,常用 reg 类型,默认初始值为X(未知)。

//reg define
reg [31:0] delay_cut;  //32位寄存器
reg        key_reg;    //默认位宽为 1

只能在 always 语句和 initial 语句中被赋值。(不允许像C语言一样,在定义同时赋值)
如果该过程语句描述的是时序逻辑,即 always 语句带有时钟信号,则该寄存器变量对应为寄存器;
如果该过程语句描述的是组合逻辑,即 always 语句不带有时钟信号,则该寄存器变量对应为硬件连线。

线网类型

表示结构化实体(e.g.门)的物理连线。不能存储值,它的值由驱动它的元件决定。驱动元件有连续赋值、门、assign等。默认是Z高阻态。 有tri 和 wire型。

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

参数类型

参数其实就是一个常量,用parameter定义(类似C语言中的define)我们可以一次定义多个参数,参数与参数之间需要用逗号隔开。参数的定义是局部的,只在当前模块中有效。

//parameter define
parameter DATA_WIDTH = 8; //数据位宽为8位
//可以[DATA_WIDTH : 0]只修改参数值来修改位宽

参数型数据用于定义状态机的状态、数据位宽和延迟大小等,在模块调用时可以通过参数传递来改变调用模块中已定义的参数。

运算符

算术运算符: Verilog 实现乘除比较浪费组合逻辑资源,尤其是除法。所以 2 的指数次幂的乘除习惯用移位,非 2 的指数次幂的乘除调用现成的 IP(ISE提供)
关系运算符
逻辑运算符: !、&& 、 ||
条件操作符: a ? b : c
位运算符: ~(取反)、&、 |、^(异或)
移位运算符: << a << b 将 a 左移 b 位
左移时位宽增加,右移时位宽不变。
4‘b1001 <<2 = 6’b100100
拼接运算符: {a,b} 将 a 和 b 拼接起来作为一个新信号。

二、Verilog程序框架

Verilog注释

//与/* */

Verilog关键字

关键字 含义
module 模块开始定义
input 输入端口定义
output 输出端口定义
inout 双向端口定义
parameter 信号的参数定义
wire wire信号定义
reg reg信号定义
always 产生reg信号语句的关键字
assign 产生wire信号语句的关键字
begin 语句的起始标志
end 语句的结束标志
posedge/negedge 时序电路的标志
case Case语句起始标记
default Case语句的默认分支标志
endcase Case语句结束标记
endmodule 模块结束定义

Verilog程序框架

基本设计单元是模块(Block),类比C语言中的函数。
模块由两部分组成,一部分描述接口,一部分描述逻辑功能,
每个Veirlog程序包括端口定义、IO说明、内部信号说明、功能定义。下面以程序示例讲解知识点。

//     模块名(端口定义);
module block(a,b,c,d);//IO说明input a,b;output c,d;   /************************************************1.未说明类型就是wire类型,reg类型定义为:output reg [3:0] led //在位宽之前加reg2.端口定义和IO说明可以放在一起,例如module led( input sys_clk , //系统时钟input sys_rst_n, //系统复位,低电平有效output reg [3:0] led //4 位 LED 灯  );  ************************************************///内部信号说明就是只在此模块内部使用的一些信号,不是输入输出/************************************************功能定义:3种方法:assign描述组合逻辑always描述组合/时序逻辑例化示例元件 例如 and #2 u1(q,a,b)   3种逻辑功能是并行的************************************************///assign 给wire类型赋值assign c = a|b;assign d = a&b;
endmodule

模块调用、例化——模块化设计

Verilog 语法中的模块例化。FPGA 逻辑设计中通常是一个大的模块中包含了一个或多个功能子模块,Verilog 通过模块调用或模块实例化来实现这些子模块与高层模块的连接。【把系统划分为几个模块,每个模块对应一个module,一个module一个Verilog程序文件。顶层模块只做例化(调用其它模块),不做逻辑。】

首先将被调用模块例化,例化模块名加u_

//顶层模块
module seg_led_static_top ( input sys_clk , // 系统时钟input sys_rst_n, // 系统复位信号(低有效)output [5:0] seg_sel , // 数码管位选output [7:0] seg_led // 数码管段选  );//parameter defineparameter TIME_SHOW = 25'd25000_000; // 数码管变化的时间间隔 0.5s//wire definewire flag; // 数码管变化的通知信号//每隔 0.5s 产生一个时钟周期的脉冲信号
time_count #(.MAX_NUM (TIME_SHOW) //参数TIME_SHOW控制数码管每隔多长时间改变显示的数值,底层代码给参数MAX_NUM了值,此处也是一种参数赋值方式,就是把TIME_SHOW的值给MAX_NUM) u_time_count(  //例化模块名加_u.clk (sys_clk ),   //由模块代码看以看到clk是模块的输入.rst_n (sys_rst_n),//所以这就是把上层模块的信号输入到底层模块,这里()里可以是wire或者reg,而下面的output的连接必须是wire型的.flag (flag ) //而底层模块的输出信号是连接到了上层模块中定义的其他变量 //信号传递的时候信号的位宽必须一致);//属于底层文件
//计时模块代码module time_count( input clk , // 时钟信号input rst_n , // 复位信号output reg flag // 一个时钟周期的脉冲信号
);parameter MAX_NUM = 25000_000; // 计数器最大计数值
reg [24:0] cnt; // 时钟分频计数器

三、Verilog高级知识点

结构语句

initial与always

initial:
只执行一次,立即执行,用于tb文件编写,产生激励信号或对reg变量赋初值。

initial beginsys_clk          <= 1b'0;touch_key        <= 1b'0;#10 touch_key    <= 1b'1;
end

always:
一直执行,但需要结合一定的时间控制才有作用
always的时间控制可以是电平触发也可是边沿触发。可以是单个信号也可以是多个信号,多个信号用or连接

/**************边沿触发(时序逻辑行为)**************/
//用于产生 0.5 秒使能信号的计数器//@()里的多个事件名或信号名组成的列表叫做敏感列表,只有满足敏感列表才能执行后面的语句
always @(posedge sys_clk or negedge sys_rst_n) beginif (sys_rst_n == 1'b0) counter <= 1'b0;else if (counter_en)counter <= 1'b0;elsecounter <= counter + 1'b1;
end/**************电平触发(组合逻辑行为)**************/
always @(a or b or c or d or e) beginout1 = a ? (b + c) : (d + e);
end
//如果输入变量很多,敏感列表就很长且易错
always @( * ) begin  //表示后面语句块中所有输入变量都是敏感的out1 = a ? (b + c) : (d + e);
end

赋值语句

分为阻塞赋值和非阻塞赋值;RHS(Right hand side)是赋值符号右侧信号, LHS是左侧

阻塞赋值(Blocking)

b = a;
计算 RHS 的值并更新 LHS。

在一个 always 块中,后面的赋值语句是在前一句赋值语句结束后才开始赋值的。即 always 块内的语句是一种顺序关系。

非阻塞赋值(Non-Blocking)

b <= a;
(1)赋值开始的时候,计算 RHS;
(2)赋值结束的时候,更新 LHS。
在计算非阻塞赋值的 RHS 以及 LHS 期间,允许其它的非阻塞赋值语句同时计算 RHS 和更新 LHS。
非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial和always块等过程块中。

需要注意的是赋值语句是一直在always中执行,所以随着clk的上升沿一直来,bc最后也都变成a =0;

总结

1.描述组合逻辑电路,用阻塞赋值,比如 assign 赋值语句和不带时钟的 always 赋值语句,这种电路结构只与输入电平的变化有关系
2.描述时序逻辑电路,用非阻塞赋值,综合成时序逻辑的电路结构,比如 带时钟的 always 语句;这种电路结构往往与触发沿有关系,只有在触发沿时才可能发生赋值的变化
注意 :

  • 同一个always中不要既用阻塞又用非阻塞
  • 不允许在多个always中对同一个变量赋值(因为并行执行)
assign 和 always 区别

assign 不能带时钟。 always 可以带也可以不带。在 always 不带时钟时,逻辑功能和 assign 完全一致,都只产生组合逻辑。比较简单的组合逻辑推荐使用 assign 语句,比较复杂的组合逻辑推荐使用 always 语句。

 assign counter_en = (counter == (COUNT_MAX - 1'b1)) ? 1'b1 : 1'b0; always @(*) begincase (led_ctrl_cnt) 2'd0 : led = 4'b0001;51 2'd1 : led = 4'b0010;2'd2 : led = 4'b0100;2'd3 : led = 4'b1000;54 default : led = 4'b0000; endcase
end

条件语句

if_else语句:

1.必须在过程块(有initial和always语句引导的)中使用
2.表达式值为X,Z时按假处理
3.if之后如果多句,要用begin end
4.不允许if嵌套

case语句:

与C中的case不同,没有switch关键字。

 case (curr_st)4'h0: next_st = S1;4'h1: next_st = S2;4'h2: next_st = S3;4'h3: next_st = S4;default: next_st = S0;endcase

1.所有表达式的位宽必须相等,不能用’bx代替n’bx,
2.casez:比较时不考虑z
casex:比较时不考虑z和x

reg [7:0] sel; //1100_0011
casez(sel)   //这种就不用考虑下面表达式中的高阻值8'b1100_zzzz:语句1;8'b1100_xxzz:语句2;//xx与00不相等,所以执行语句1
endcasecasex(sel)此时两个表达式相当于相同了,error!

latch锁存器

锁存器是电平触发的存储器,是组合逻辑产生的,寄存器是边沿触发的存储器,在时序电路中使用,由时钟触发产生的。
if 缺少 else 分支,case 缺少 default 分支会导致代码在综合过程中出现了 latch。latch只在组合逻辑电路中产生,也就是只有不带时钟的 always 语句中 if 或者 case 语句不完整才会产生 latch,带时钟的语句 if或者 case 语句不完整描述不会产生 latch。

四、Verilog状态机FSM

状态机FSM概念

我们一直在强调硬件描述语言是并行执行的,所以如果按顺序流程来完成一个操作的时候,就需要很多的if_else,降低了代码的可读性,也让代码编写难度增加(与单片机编写程序的区分)。所以就需要引入状态机,将一项功能的完成分解为若干步,每一步对应于二进制的一个状态,通过预先设计的顺序在各状态之间进行转换,状态转换的过程就是实现逻辑功能的过程,就像数电里学过的画状态转换图/表。
状态机,(Finite State Machine,FSM有限状态机)一种在有限个状态之间按一定规律转换的时序电路,是组合逻辑和时序逻辑的组合。

状态机模型

Mealy状态机(输出=输入+之前状态)

  • F 是当前状态和输入信号的函数,状态是否改变、如何改变,取决于组合逻辑 F 的输出;
  • 状态寄存器,其由一组触发器组成,用来记忆状态机当前所处的状态,状态的改变只发生在时钟的跳边沿;
  • 状态机的输出是由输出组合逻辑 G 提供的,G 也是当前状态和输入信号的函数。

Moore 状态机(输出=之前状态)


Moore型不是没有输入,而是输出与输入无关。

状态机设计

四段论:

  • 状态空间定义;
  • 状态跳转;
  • 下个状态判断;
  • 各个状态下的动作;

1.状态空间定义

/************************方法1:************************/
//state space
parameter S0 = 2'b00;
parameter S1 = 2'b01;
parameter S2 = 2'b10;
parameter S3 = 2'b11;
// internal varialbe
reg [1:0] current_state;
reg [1:0] next_state;/************************方法2:推荐************************/
//独热码:每个状态只有一个寄存器置位,译码逻辑简单
//state space
parameter S0 = 2'b1000;
parameter S1 = 2'b0100;
parameter S2 = 2'b0010;
parameter S3 = 2'b0001;
// internal varialbe
reg [3:0] current_state;
reg [3:0] next_state;

2.状态跳转(时序逻辑)

就是上面框图中的状态寄存器

always @(posedge clk or negedge rst_n) beginif(!rst_n)current_state <= S0;elsecurrent_state <= S1;

3.下一个状态的判断(组合逻辑)

就是上面框图中的产生下一状态的组合逻辑F

always @(current_state  or input signals) begincase(current_state )  //强烈建议使用case 而不用if_elseS0: beginif(a)next_state = S1;else next_state = S0;S1:.......;S2:.......;S3:.......;default:.......;endcase
end

4.各个状态下的动作(组合逻辑)

就是上面框图中的产生输出的组合逻辑G

//action
wire qook;
assign qook = (current_state == S1) ? 1'b1 : 1'b0;//下面是用always写上面的语句
always @(current_state ) beginif(current_state == S1)qook = 1;else qook = 0;
end

总结

这里我们实际用了一个三段式状态机。基本格式是:
第一个 always 语句实现同步状态跳转;
第二个 always 语句采用组合逻辑判断状态转移条件;
第三个 always 语句描述状态输出(可以用组合电路输出,也可以时序电路输出)。

  • 可以在组合逻辑之后再加一级寄存器实现时序逻辑输出

    1.滤除组合逻辑输出的尖峰脉冲
    2.进行时序计算和约束
    3.对于总线形式的输出信号来说,容易使总线数据对齐,减小总线数据间的偏移,减小接收数据采样出错的频率。比如8位位宽信号,如果用组合逻辑,可能导致并行的8个数据从输入端到达输出端的时间不一致。

FPGA语法篇——Verilog 语法知识相关推荐

  1. FPGA 40 专题 verilog语法编程规范

    FPGA 40 专题 verilog语法编程规范 在这里主要是给自己写一个备忘录,加强个人记忆. 详细可以参考地址1:https://www.runoob.com/w3cnote/verilog2-c ...

  2. FPGA笔记1——Verilog语法

    目录 一.Verilog基础语法 1.1 逻辑值: 1.2 数字进制: 1.3 标识符 1.4 数据类型: 寄存器 线网 参数类型 1.5 运算符 二.Verilog程序框架 2.1 注释 2.2 关 ...

  3. 英语语法篇 - 英语语法综述

    文章目录 简单句 英语的5种基本句型: 八大句子成分 复杂句和复合句 复杂句 从句(4 + 2) 同一类句子成分里可能有不同的词类. 十大词性(词类) 谓语动词 非谓语动词 总结 简单句 没法再拆成更 ...

  4. FPGA笔记之verilog语言(基础语法篇)

    文章目录 FPGA笔记之verilog语言(基础语法篇) 1. verilog 的基础结构 1.1 verilog设计的基本单元--module 1.2 module的使用 1.3 I/O的说明 1. ...

  5. Cyclone FPGA踏足笔记(二):Verilog语法学习总结

    欢迎来我的个人博客:https://codinglover.top/ 转转! 前言 花了一个月时间零零碎碎看了下Verilog的语法,终于把Verilog的基本语法学了个大概,可以自己写点小东西了,由 ...

  6. Verilog 语法入门知识

    Verilog 语法入门知识 一.变量类型 ①数值 数值表示采用 <二进制位数>'<数值表示的进制><数值>的结构. 其中进制可以为b.o.d.h分别代表二.八.十 ...

  7. 【FPGA】——Verilog语法

    简介 (一)概述 Verilog是一种硬件描述语言,以文本形式来描述数字系统硬件的结构和行为的语言,可表示逻辑电路图.逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能. 数字电路设计者利用这种语言, ...

  8. [转]verilog语法学习心得

    verilog语法学习心得 1.数字电路基础知识: 布尔代数.门级电路的内部晶体管结构.组合逻辑电路分析与设计.触发器.时序逻辑电路分析与设计 2.数字系统的构成: 传感器  AD  数字处理器  D ...

  9. Verilog语法和典型电路

    这里写目录标题 Verilog语法知识 Q:锁存器 Q:D触发器 Q:消除毛刺 Q:同步复位和异步复位 Q:边沿检测 Q:握手信号 Q:脉冲展宽(单bit慢采快) Q:二进制与格雷码的转换 Q:二进制 ...

  10. Flex 布局教程:语法篇

    阮一峰的网络日志 » 首页 » 档案 上一篇:ES6 的功能侦测库 下一篇:Flex 布局教程:实 分类: 开发者手册 Flex 布局教程:语法篇 作者: 阮一峰 日期: 2015年7月10日 网页布 ...

最新文章

  1. 随笔(2018.8.31)
  2. Ubuntu16.04LTS安装ROS Kinetic
  3. 职业化之可以固化的六个工作模式
  4. ldap的shema
  5. 主从复制中忽略库的参数
  6. 韩国财长:韩国将按计划推进加密货币征税
  7. android UI 标签
  8. Orchard Core 使用工作流处理页面提交
  9. MySQL备份与恢复-innobackupex
  10. linux如何查看内存?
  11. 【项目管理/PMP/PMBOK第六版/新考纲】计算题! 假设情景分析/类比估算/处理变更/结束采购/高层级风险/组织过程资产
  12. 获取google chrome浏览器的安装位置
  13. C51 基本函数、中断函数和库函数的详解
  14. 网络——路由进阶与安全
  15. Jacoco 入门使用
  16. 领域模型-软件需求分析
  17. Android ExpandableListView 使用实例
  18. 淋巴瘤最新研究进展(2022年4月)
  19. 分水岭变换的分割,watershed函数
  20. OpenGL glut OFF 读取 + 半边数据结构存储

热门文章

  1. flash builder 4.6 mac 版破解方法
  2. 实用供热空调设计手册_空调水系统管路设计与施工,全是最实用的现场经验!...
  3. MAC中生成SSH key
  4. 正逆运动学解(三维)
  5. winhex数据恢复入门教程
  6. RANSAC算法(原理及代码实现+迭代次数参数自适应)
  7. 这三个方法让你实现电脑截图转文字的操作
  8. chrome拓展 --截屏文字识别
  9. 如何把word ppt 思维导图这类文件转化为高清晰度的图片(要干货只看粗体黑字)
  10. android获取显示屏尺寸大小,Android 屏幕各尺寸的获取