[SugerTangYL] Verilog 语言入门(零基础视角)

目录

前言

一、示例

1.一位全加器功能及电路图

2.一位全加器Verilog代码

(1)模块定义声明

 (2)变量声明定义

(3)子模块调用

二、模块声明定义模板

总结


前言

hi guys,这是我第一篇博客23333,本人准备走数字IC设计,在对岗位了解了之后便萌生了写博客来记录自己的学习成果,同时给对该行业以及本专业的学弟学妹摸摸路子(可能有作业思路提供)


一、示例

        在进入Verilog语言语法之前,先抛出一个示例看看。对数字电路来说,大家接触最多的应该是一位全加器叭,下面就以一位全加器的RTL代码以及电路来理解Verilog语言的特点。

1.一位全加器功能及电路图

        一位全加器是用来计算低位进位的二进制加法器,其实现的逻辑表达式如下:

                         S=A\oplus B\oplus Ci                            Co=(A\cdot B)+(Ci\cdot (A\oplus B))​​​​​​

        至于真值表咱就不列啦,一位全加器的原理在此不讲述,将逻辑表达式变成实际电路,需要两个异或门和三个与非门总共五个模块,电路图如下(使用Quartus II 15.0画的):

        这个电路很熟悉了叭!数电学的就这个电路,有A、B、Ci三个输入和S、Co两个输出,那我们就是用Verilog语言来描述这个电路,让电脑转化你写的RTL代码成这个电路图。那下面便是上述电路对应的Verilog代码,代码与电路之间等效。

2.一位全加器Verilog代码

module example(A,B,Ci,Co,S);

input wire	A;
input wire	B;
input wire	Ci;
output wire	Co;
output wire	S;

wire OUT_nand1,OUT_nand2,OUT_xor1;

xor xor1(OUT_xor1,A,B);
xor xor2(S,OUT_xor1,Ci);
nand nand1(OUT_nand1,A,B);
nand nand2(OUT_nand2,OUT_xor1,Ci);
nand nand3(Co,OUT_nand1,OUT_nand2);

endmodule 

         上面就是一位全加器的Verilog代码啦,会不会看不懂(dog),接下来我将介绍各部分的对应含义。

(1)模块定义声明

module fulladder_1bit(A,B,Ci,Co,S);

......

endmodule  

         这段代码的头和尾便是对模块的定义声明,他有以下特点:

  • 以关键词(module)开始,关键词(endmodule)结束,中间便是模块的内容。
  •  fulladder_1bit为这个模块的名称。
  • 名称后面的(A,B,Ci,Co,S)为模块的输入输出列表,表示此模块有哪些输入输出“变量”。
  • 在module声明这一行末尾有“ ;” 结束!!!

 (2)变量声明定义

input wire    A;
input wire    B;
input wire    Ci;
output wire    Co;
output wire    S;

wire OUT_nand1,OUT_nand2,OUT_xor1;

         input是输入变量声明的关键字,output是输出变量声明的关键字。wire是变量类型,表示线网类型。因此“input wire A;”表示声明一个输入变量A,其属性为线网类型,线宽是一位(未定义位宽则默认一位)。变量类型放在之后详细介绍。

        对于最底下那行,最前面没有出现input和output,便表示这些变量为内部变量。

(3)子模块调用

xor xor1(OUT_xor1,A,B);
xor xor2(S,OUT_xor1,Ci);
nand nand1(OUT_nand1,A,B);
nand nand2(OUT_nand2,OUT_xor1,Ci);
nand nand3(Co,OUT_nand1,OUT_nand2);

        从电路图看的出来,一个一位全加器模块由两个异或门和三个与非门组成。于是我们只需要在一位全加器这个模块内部,调用两个异或门和三个与非门模块。

  • xor是异或门的关键字,nand是与非门的关键词。
  • xor1、xor2、nand1、nand2、nand3分别是这五个模块的名字(实例化),这个名字可以忽略不写,软件将自动帮你补上名字。
  • 与前面相同,括号内为模块的输入输出列表。

 至此这个一位全加器的所有部件齐全,编译后用RTL Viewer观察生成的RTL电路,如下:

         上例便是Verilog建模中的“门级建模”。这时候你可能会说“啊啊啊啊要是更复杂的功能难道都要用最基本的门去搭嘛那不得麻烦死啊啊啊”。当然,在实现更复杂的逻辑时,门级建模的难度会急剧上升,因此我们还有数据流建模(组合逻辑电路)和行为级建模(时序逻辑电路),甚至任务和函数,来帮助我们更高效、更具逻辑性的编写Verilog代码。具体的语言语法在此不介绍。

二、模块声明定义模板

综上,对模块的定义模板如下:

module <模块名>(<输入输出列表>);

input <变量类型> <变量位宽> <变量名>;
output <变量类型> <变量位宽> <变量名>;
<变量类型> <变量位宽> <变量名>;//内部变量声明

<子模块名> <实例化名称> (<子模块输入输出列表>)

assign ……//数据流描述

always ……//行为级描述

function ……//函数

task ……//任务

endmodule

        其中除了最开始的模块声明以及输入输出变量的声明是必须之外,其他都是可选择性的编写。有一张对模块组成很好诠释的框图。 


总结

        上面就是Verilog零基础入门的示例,我们能看出Verilog的基本设计单元为模块,模块与模块之间的区别便是内部所含电路的不同,对内部电路的描述方法也有好几种。因此,我们只需要把每个部分的语法规则学好,就可以写出功能完整的Verilog代码啦。

  • 17
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
目 录 译者序 前言 第1章 简介 1 1.1 什么是Verilog HDL? 1 1.2 历史 1 1.3 主要能力 1 第2章 HDL指南 4 2.1 模块 4 2.2 时延 5 2.3 数据流描述方式 5 2.4 行为描述方式 6 2.5 结构化描述形式 8 2.6 混合设计描述方式 9 2.7 设计模拟 10 第3章 Verilog语言要素 14 3.1 标识符 14 3.2 注释 14 3.3 格式 14 3.4 系统任务和函数 15 3.5 编译指令 15 3.5.1 `define和`undef 15 3.5.2 `ifdef、`else 和`endif 16 3.5.3 `default_nettype 16 3.5.4 `include 16 3.5.5 `resetall 16 3.5.6 `timescale 16 3.5.7 `unconnected_drive和 `nounconnected_drive 18 3.5.8 `celldefine 和 `endcelldefine 18 3.6 值集合 18 3.6.1 整型数 18 3.6.2 实数 19 3.6.3 字符串 20 3.7 数据类型 20 3.7.1 线网类型 20 3.7.2 未说明的线网 23 3.7.3 向量和标量线网 23 3.7.4 寄存器类型 23 3.8 参数 26 第4章 表达式 28 4.1 操作数 28 4.1.1 常数 28 4.1.2 参数 29 4.1.3 线网 29 4.1.4 寄存器 29 4.1.5 位选择 29 4.1.6 部分选择 29 4.1.7 存储器单元 30 4.1.8 函数调用 30 4.2 操作符 30 4.2.1 算术操作符 31 4.2.2 关系操作符 33 4.2.3 相等关系操作符 33 4.2.4 逻辑操作符 34 4.2.5 按位操作符 35 4.2.6 归约操作符 36 4.2.7 移位操作符 36 4.2.8 条件操作符 37 4.2.9 连接和复制操作 37 4.3 表达式种类 38 第5章 门电平模型化 39 5.1 内置基本门 39 5.2 多输入门 39 5.3 多输出门 41 5.4 三态门 41 5.5 上拉、下拉电阻 42 5.6 MOS开关 42 5.7 双向开关 44 5.8 门时延 44 5.9 实例数组 45 5.10 隐式线网 45 5.11 简单示例 46 5.12 2-4解码器举例 46 5.13 主从触发器举例 47 5.14 奇偶电路 47 第6章 用户定义的原语 49 6.1 UDP的定义 49 6.2 组合电路UDP 49 6.3 时序电路UDP 50 6.3.1 初始化状态寄存器 50 6.3.2 电平触发的时序电路UDP 50 6.3.3 边沿触发的时序电路UDP 51 6.3.4 边沿触发和电平触发的混合行为 51 6.4 另一实例 52 6.5 表项汇总 52 第7章 数据流模型化 54 7.1 连续赋值语句 54 7.2 举例 55 7.3 线网说明赋值 55 7.4 时延 55 7.5 线网时延 57 7.6 举例 57 7.6.1 主从触发器 57 7.6.2 数值比较器 58 第8章 行为建模 59 8.1 过程结构 59 8.1.1 initial 语句 59 8.1.2 always语句 61 8.1.3 两类语句在模块中的使用 62 8.2 时序控制 63 8.2.1 时延控制 63 8.2.2 事件控制 64 8.3 语句块 65 8.3.1 顺序语句块 66 8.3.2 并行语句块 67 8.4 过程性赋值 68 8.4.1 语句内部时延 69 8.4.2 阻塞性过程赋值 70 8.4.3 非阻塞性过程赋值 71 8.4.4 连续赋值与过程赋值的比较 72 8.5 if 语句 73 8.6 case语句 74 8.7 循环语句 76 8.7.1 forever 循环语句 76 8.7.2 repeat 循环语句 76 8.7.3 while 循环语句 77 8.7.4 for 循环语句 77 8.8 过程性连续赋值 78 8.8.1 赋值—重新赋值 78 8.8.2 force与release 79 8.9 握手协议实例 80 第9章 结构建模 83 9.1 模块 83 9.2 端口 83 9.3 模块实例语句 83 9.3.1 悬空端口 84 9.3.2 不同的端口长度 85 9.3.3 模块参数值 85 9.4 外部端口 87 9.5 举例 89 第10章 其他论题 91 10.1 任务 91 10.1.1 任务定义 91 10.1.2 任务调用 92 10.2 函数 93 10.2.1 函数说明部分 93 10.2.2 函数调用 94 10.3 系统任务和系统函数 95 10.3.1 显示任务 95 10.3.2 文件输入/输出任务 97 10.3.3 时间标度任务 99 10.3.4 模拟控制任务 99 10.3.5 定时校验任务 100 10.3.6 模拟时间函数 101 10.3.7 变换函数 102 10.3.8 概率分布函数 102 10.4 禁止语句 103 10.5 命名事件 104 10.6 结构描述方式和行为描述方式的 混合使用 106 10.7 层次路径名 107 10.8 共享任务和函数 108 10.9 值变转储文件 110 10.9.1 举例 111 10.9.2 VCD文件格式 112 10.10 指定程序块 113 10.11 强度 114 10.11.1 驱动强度 114 10.11.2 电荷强度 115 10.12 竞争状态 116 第11章 验证 118 11.1 编写测试验证程序 118 11.2 波形产生 118 11.2.1 值序列 118 11.2.2 重复模式 119 11.3 测试验证程序实例 123 11.3.1 解码器 123 11.3.2 触发器 124 11.4 从文本文件中读取向量 126 11.5 向文本文件中写入向量 127 11.6 其他实例 128 11.6.1 时钟分频器 128 11.6.2 阶乘设计 130 11.6.3 时序检测器 132 第12章 建模实例 136 12.1 简单元件建模 136 12.2 建模的不同方式 138 12.3 时延建模 139 12.4 条件操作建模 141 12.5 同步时序逻辑建模 142 12.6 通用移位寄存器 145 12.7 状态机建模 145 12.8 交互状态机 147 12.9 Moore有限状态机建模 150 12.10 Mealy型有限状态机建模 151 12.11 简化的21点程序 153 附录 语法参考 157 参考文献 172

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值