如何编写一个基本的 Verilog Module(模块)
1、概述
这篇文章主要介绍了 Verilog 在 FPGA 设计中的概念和使用方法。首先讨论使用模块(module)关键字构造 Verilog 设计的方式,以及这与所描述的硬件的关系。这包括对参数、端口(port)和例化(instantiaton)的讨论及一个完整示例。
虽然不需要为了使用它而讨论Verilog的整个发展历史,但是却必须考虑另一个重点——所使用的Verilog语言版本。Verilog 的主要标准发布于1995年(Verilog-1995)和2001年(Verilog-2001)。除此之外,2005年(Verilog-2005)还发布了另一个小更新。
原则上,我们应该为创建的任何新 FPGA 设计使用 Verilog-2001 或 Verilog-2005 标准。然而,我们可能仍然会遇到基于 Verilog-1995 标准的遗留设计。因此,我们将在这些文章中看到 Verilog-1995 标准和 Verilog-2001 年标准之间的重要区别。
2、构建 Verilog 代码
当我们设计 FPGA 时,需要记住一个基本的原则——我们是在设计硬件,而不是在编写软件程序。因此,我们必须描述许多不同电子组件(electronic component)的行为,然后将它们连接在一起。这反映在 Verilog 文件的结构方式中。
对于每个电子组件,我们需要知道组件的外部接口。此信息使我们能够将其连接到我们系统中的其他组件。我们还需要知道组件的行为方式,以便我们可以在我们的系统中使用它。
在 Verilog 中,我们使用称为模块(module)的构造来定义此信息。Verilog中的module相当于VHDL中的 entity architecture pair。
下面的代码片段显示了在 Verilog 中声明模块的一般语法。
module ( //module开始//定义参数parameter <parameter_name> = <default_value>
)
<module_name> (//IO定义<direction> <data_type> <size> <port_name>
);//完整的RTL代码endmodule //module结束
在此构造中,<module_name> 是正在设计的模块的名称。虽然我们可以在一个文件中声明多个模块,但最好让一个文件对应一个模块(好的开发习惯)。保持文件名和模块名相同也是一种很好的做法。这会让管理包含许多层级的大型设计变得更加简单。
在 Verilog 中,我们使用 // 字符来表示我们正在编写注释。我们使用注释来包含有关我们代码的重要信息,这些信息可能会帮助到其他人理解代码。Verilog 编译器会忽略我们在注释中写的任何内容。
在上面的 Verilog 代码片段中,我们可以看到这一点,因为这些注释仅用于描述代码的功能。
2.1、Verilog-1995 模块(Modules)
Verilog 模块声明语法作为 verilog-2001 标准的一部分进行了更新。这意味着用于在 Verilog 中声明模块的方法会略有不同。
使用 Verilog-1995 代码时,我们仅在初始模块声明中定义端口名称。然后我们在模块主体中定义每个端口的方向、数据类型和大小。除此之外,我们还在模块中定义了模块参数。
下面的代码片段显示了如何使用 Verilog-1995语法来声明模块。
module <module_name> (// All IO names are defined here<port_name>
);//在这里声明参数,可选项parameter <parameter_name> = <default_value>;//IO定义<direction> <data_type> <size> <port_name>;//完整的RTL代码endmodule
2.2、Verilog 模块中的参数(Parameters)
参数(parameter)是常量(constant)的局部形式,我们可以使用它来配置 Verilog 中的模块。当我们在设计的另一部分实例化我们的模块时,可以为参数分配一个值来配置模块的行为。
由于参数的作用域有限,所以我们可以多次调用同一个模块,每次都为参数赋不同的值。因此,参数允许我们随时修改模块的行为。
参数是 Verilog 模块声明的可选部分,在大多数情况下我们并不需要使用它们。然而,参数允许我们编写更通用的模块接口,这些接口更容易在其他 Verilog 设计中被复用。
在模块中声明了一个参数之后,我们就可以像使用普通变量一样使用它。但是,必须记住--参数是一个常量值,所以只能读取它。因此,我们只能在参数声明时为其赋值。
2.3、功能代码
我们使用模块 IO 声明下方的空间来定义模块的功能。我们最常为此使用RTL(Register Transfer Level),但也可以编写结构代码或描述性原语。
我们使用关键字 module 开始一个模块的设计,从关键字 module 到关键字 endmodule 内的所有内容构成了一个完整的模块。
当我们完成描述模块行为的代码时,使用 endmodule 关键字来作为结束。在此关键字之后编写的任何代码都不会包含该模块中。
2.4、Verilog 模块端口(Ports)
我们在模块声明中使用端口来定义 Verilog 模块的输入和输出。可以近似地认为这些端口相当于传统电子元件中的管脚。
下面的代码片段显示了我们用来声明端口的一般语法。
<direction> <data_type> <size> <port_name>
<direction> :我们可以在 Verilog 模块中将端口定义为in(输入)、out(输出)或 inout(双向端口)。上述构造中的可用于执行此操作。
<port_name> :字段用于为端口指定一个唯一的名称。
<data_type> :声明端口的数据类型,最常见的类型是reg 和 wire 。
<size> :用来表述端口多位向量的位数。当我们定义向量类型输入的大小时,我们必须指出向量中的最高有效位(most significant bit,MSB)和最低有效位(least significant bit,LSB)。因此,我们在声明端口大小时使用 [MSB:LSB]。
下面的示例显示了名为 example_in 的 8 位输入的声明。
input wire [7:0] example_in;
在此示例中,[7:0] 表示第 7 位是最高有效位。这称为小字节序或低字节序(little endian),是 FPGA 设计中最常用的表示方法。
如果我们将声明改为 [0:7],也可以将 MSB 定义为位置 0。这种称为大字节序或高字节序(big endian)的表示方法在设计 FPGA 时不像小字节序那样常用。
2.5、Verilog 中的 Reg 和 Wire 类型
Verilog中的数据类型有很多,但是最常用的只有两种--reg 和 wire。
wire 类型被用来来声明信号,这些信号在我们的 Verilog 代码中是简单的点对点连接(电线)。因此,电线不能驱动数据,也不能存储数值。顾名思义,它们大致相当于传统电路中的一根导线。
reg 类型被用来声明一个信号,该信号在我们的 Verilog 代码中主动驱动数据。顾名思义,它们大致相当于传统数字电路中的触发器(flip flop)。
由于wire类型是基本的点对点连接,所以我们可以在声明 Verilog 模块时将wire用作in或者out类型。相反,reg 类型只能用于 Verilog 模块中的输出。
wire类型主要被用来构建组合逻辑电路,当我们使用 assign 关键字在 Verilog 中对组合逻辑建模时,我们只能将其与wire类型一起使用。
reg 类型主要被用来构建时序逻辑电路,我们必须使用always块(always block)来为时序逻辑电路建模。我们只能在 always 块中使用 reg 类型。
在声明模块端口时,其默认数据类型是wire。因此,当我们使用wire端口时,可以省略掉wire这个关键字,但是reg关键字则不能被省略。
3、Verilog 模块例化(Instantiation)
我们可以调用已经在设计的另一部分编写的 Verilog 模块。在 Verilog 中调用模块的过程称为实例化(实例化,instantiation)。
每次例化一个模块时,都会创建一个唯一的对象(Object),它有自己的名称、参数和端口。
在 Verilog 设计中,我们将每个例化模块称为模块的实例(instance)。我们使用例化来创建许多不同的实例,并用它们来构建更复杂的设计。
我们可以认为Verilog中的模块例化相当于在传统电子电路中放置了一个电子元件。一旦我们创建了设计中需要的所有实例,就必须将它们互连以创建一个完整的系统。这与在传统电子系统中将组件接线在一起完全相同。
Verilog 为我们提供了两种可用于模块实例化的方法——命名例化(named instatiation)和位置例化(positional instatiation)。
Verilog-2001 标准编支持以上两种例化方式,而Verilog-1995标准只支持位置例化方法。
3.1、位置例化方法
在 Verilog 中使用位置例化方法时,需要使用有序列表来连接模块端口。被例化的模块实例的端口顺序必须与我们模块中声明端口的顺序一样。
例如,如果我们依次声明时钟clock,复位rst,那么我们在例化时就必须先将时钟信号连接到模块端口。
下面的 Verilog 代码片段显示了位置模块例化方法的一般语法。
<module_name> # (//例化的参数列表<parameter_value>
)
<instance_name> (//例化的端口,需要按照被例化模块的顺序排列出来<signal_name>, //第一个端口<signal_name> //第二个端口
);
<module_name> :必须与在声明模块时给它的名称相匹配。
<instance_name>:设计中的例化模块的唯一名称。
这种方法可能难以维护,因为我们的端口顺序可能会随着我们设计的发展而改变。
下面看一个简单的例子来展示如何使用位置例化方法。对于这个例子,我们将创建一个如下所示的简单电路的实例。
当我们使用位置例化方法时,模块声明中端口的顺序很重要。下面的代码片段显示了如何为这个电路声明一个模块。
and_or (input a,input b,input c,output logic_out
);
下面的 Verilog 代码片段显示了如何使用位置例化方法来创建此模块的实例。
and_or example_and_or (in_a,in_b,in_c,and_or_out
);
3.2、命名例化方法
在 Verilog 中使用命名例化方法时,我们需要明确定义将信号连接到的端口的名称。与位置例化方法不同的是--声明端口的顺序并不重要。
这种方法通常优于位置例化方法,因为它生成的代码更易于阅读和理解。它也更容易维护,因为我们可以修改端口而不必担心我们声明它们的顺序。
下面的 Verilog 代码片段显示了命名模块实例化的一般语法。
<module_name> # (//被例化的参数与例化的参数.<parameter_name> (<parameter_value>)
)
<instance_name> (//被例化的端口与例化的端口.<port_name> (<signal_name>),.<port_name> (signal_name>)
);
<module_name>、<parameter_name> 和 <port_name> 必须与在定义模块时使用的名称相匹配。
<instance_name> 对位置例化和命名例化具有相同的功能。
使用上一节用到的电路作为简单案例来展示如何使用命名例化方法。
下面的 Verilog 代码片段显示了我们如何使用命名例化创建此模块的实例。
and_or example_and_or (.a (in_a),.b (in_b),.c (in_c),.logic_out (and_or_out)
);
4、完整的Verilog module示例
为了完全理解我们在这篇文章中讨论的所有概念,让我们看一个基本示例。
在这个例子中,我们将创建一个使用参数的同步计数器电路,然后实例化它的两个实例。
这些实例之一将在输出中具有 12 位,而另一个将只有 8 位。
我们将在这里排除这些模块的 RTL,因为我们还没有学会如何编写它。相反,我们将简单地定义模块的 IO 以及它们之间的互连。
计数器模块将有两个输入——时钟和复位——和一个输出——计数器值。
除此之外,我们还需要一个参数来定义输出中的位数。
下面的代码片段显示了使用 verilog 2001 和 verilog 1995 兼容代码的计数器模块的声明。
// Verilog-2001
module counter #(parameter WIDTH = 8
)
(input clock,input reset,output reg [WIDTH-1:0] count
);// Verilog-1995
module counter (clock,reset,count
);paramater WIDTH = 8;input clock;
input reset;
output reg [WIDTH-1:0] count;endmodule
我们现在需要一个模块--用它来例化这个计数器的两个实例。该模块将有两个输入--时钟和复位以及两个来自例化计数器的输出。
在计数器模块中,我们定义了默认的计数器输出为 8 位。这意味着我们可以在不改变参数值的情况下实例化 8 位计数器。但是,当例化 12 位计数器时,则必须将 WIDTH 参数的值设置为 12。
下面的代码片段显示了使用命名例化方法连接到端口时此模块的代码。
module top_level (input clock,input reset,output reg [7:0] count_8,output reg [11:0] count_12
);//例化一个8bit的计数器
counter 8bit_count (.clock (clock),.reset (reset),.count (count_8)
);//例化一个12bit的计数器
counter #(.WIDTH (12)) 12_bit_count (.clock (clock),.reset (reset),.count (count_12)
);endmodule
📣您有任何问题,都可以在评论区和我交流📃!
📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!
相关文章:
如何编写一个基本的 Verilog Module(模块)
1、概述这篇文章主要介绍了 Verilog 在 FPGA 设计中的概念和使用方法。首先讨论使用模块(module)关键字构造 Verilog 设计的方式,以及这与所描述的硬件的关系。这包括对参数、端口(port)和例化(instantiato…...
让乔布斯想要「发动核战争」的 Android,为何成了占有率最高的系统?
2008 年 9 月 23 日,Apple 的创始人和 CEO 史蒂夫乔布斯像往常一样走进了公司,此时距离初代 iPhone 的发布会才过了一年半,这款充满了争议的产品就像一块从山崖滚落的巨岩,一路电光石火的给手机市场的《小石潭记》来了场焚书坑儒。…...
FPGA开发软件(vivado + modelsim)环境搭建(附详细安装步骤+软件下载)
本文详细介绍了vivado软件和modelsim软件的安装,以及vivado中配置modelsim仿真设置,每一步都加文字说明和图片。一、软件安装包下载1、vivado vivado版本很多,目前最新的已更新到vivado2022.2,版本越高,安装包越大&…...
TypeScript 学习之类型
布尔类型 类型: boolean最简单的类型,值只有 true/false let isDone: boolean true;数字类型 类型:number数字都是浮点数,支持二进制、八进制、十进制、十六进制。 let decLiteral: number 16; // 十进制 let hexLiteral: number 0xf0…...
基于MATLAB计算MIMO信道容量(附完整代码与分析)
目录 一.介绍 二. 代码 三. 运行结果及分析 3.1 MIMO信道容量:固定发射天线数为4 3.2 MIMO信道容量:固定接收天线数为4 3.3 AWGN信道与瑞利信道容量 四. 总结 一.介绍 本文章将在MATLAB环境中分析MIMO信道容量,AWGN信道容量…...
CSDN城市开发者联盟、C友会期待你的加入
文章目录🌟 课前小差🌟 chatGPT🌟 CSDN中的持续学习🌟 23年原力计划🌟 C友会、CDC🌟 如何关联本地的开发者?🌟 写在最后🌟 课前小差 哈喽,大家好,…...
【新2023】华为OD机试 - 吃火锅(Python)
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 吃火锅 题目 入职后,导师会请你吃饭,你选择了火锅, 火锅里会在不同时间下很多菜, 不同食材要煮不同时间,才能变得刚好合适, 你希望吃到最多的刚好合适的菜, 但是你的手速不够快用m代替手速, 每次…...
类似LeetCode的登录页面(小程序版)
前言每一个项目都会有用户端的注册和登录页面,对于刚入门的小白来说,在UI设计方面不太擅长,就算大致的UI界面设计出来了,但是落实到代码上来实现的时候就很容易卡住。这篇博客主要介绍的就是仿作一个类似LeetCode登录的简约大方页…...
CUDA的统一内存
CUDA的统一内存 文章目录CUDA的统一内存N.1. Unified Memory IntroductionN.1.1. System RequirementsN.1.2. Simplifying GPU ProgrammingN.1.3. Data Migration and CoherencyN.1.4. GPU Memory OversubscriptionN.1.5. Multi-GPUN.1.6. System AllocatorN.1.7. Hardware Coh…...
MySQL-其他函数(补充)
格式化函数FORMAT(x, n) 例:将数字x进行格式化,以四舍五入的方式保留n位小数,结果以字符串的形式返回mysql> select format(12.3456,3),format(2.2,4),format(9.333,0); --------------------------------------------------- | format(12…...
MySQL Study Notes Design in 2023
文章目录1 概述1.1 MySQL相关概述1.2 数据模型1.3 SQL分类2 数据库设计-DDL2.1 约束2.2 字段3 数据库操作-DML3.1 增加(insert)1 概述 1.1 MySQL相关概述 数据库:英文为 DataBase,简称DB,它是存储和管理数据的仓库。 数据库管理系统…...
C++ 修改防火墙firewall设置(Windows)
文章目录1、简介1.1 防火墙概述1.2 入站,还是出站?1.3 防火墙规则优先级2、系统界面方式3、命令行方式3.1 防火墙基本状态设置3.2 入站出站规则设置3.3 其他设置3.4 telnet检测端口4、C方式4.1 注册表4.2 COM(Windows XP)4.3 COM&…...
Spring 入门教程详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
day43【代码随想录】动态规划之一和零、完全背包理论基础
文章目录前言一、一和零(力扣474)二、完全背包前言 1、一和零 2、完全背包理论基础 一、一和零(力扣474) 求装满这个背包最多有多少个物品 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集…...
GEE学习笔记 七十八:干涸的洪泽湖
今天看了一篇报道直击60年一遇气象干旱:洪泽湖缩小近一半,鱼蟹受灾严重!_新华报业网(直击60年一遇气象干旱:洪泽湖缩小近一半,鱼蟹受灾严重!),既然玩GEE那就要玩出点花样…...
双指针【灵神基础精讲】
来源0x3f:https://space.bilibili.com/206214 文章目录同向双指针[209. 长度最小的子数组](https://leetcode.cn/problems/minimum-size-subarray-sum/)[713. 乘积小于 K 的子数组](https://leetcode.cn/problems/subarray-product-less-than-k/)[3. 无重复字符的最…...
tushare量化数据库模块怎么分析?
tushare量化数据其实包含的数据库有些是需要收费的,也有些会免费提供,不过tushare量化数据库整个库就很大很大,涉及的范围也广,挖掘这些数据还得从量化股票接口说起,就比如说在股票量化领域,tushare量化数据…...
模型转换 PyTorch转ONNX 入门
前言 本文主要介绍如何将PyTorch模型转换为ONNX模型,为后面的模型部署做准备。转换后的xxx.onnx模型,进行加载和测试。最后介绍使用Netron,可视化ONNX模型,看一下网络结构;查看使用了那些算子,以便开发部署…...
【深度学习】激活函数
上一章——认识神经网络 新课P54介绍了强人工智能概念,P55到P58解读了矩阵乘法在代码中的应用,P59,P60介绍了在Tensflow中实现神经网络的代码及细节,详细的内容可以自行观看2022吴恩达机器学习Deeplearning.ai课程,专…...
【新2023】华为OD机试 - 数字的排列(Python)
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 数字的排列 题目 小华是个很有对数字很敏感的小朋友, 他觉得数字的不同排列方式有特殊的美感。 某天,小华突发奇想,如果数字多行排列, 第一行1个数, 第二行2个, 第三行3个, 即第n行n个数字,并且…...
[oeasy]python0085_ASCII之父_Bemer_COBOL_数据交换网络
编码进化 回忆上次内容 上次 回顾了 字符编码的 进化过程 IBM 在数字化过程中 作用 非常大IBM 的 BCDIC 有 黑历史 😄 6-bit的 BCDIC 直接进化成 8-bit的 EBCDIC补全了 小写字母 和 控制字符 在ibm就是信息产业的年代 ibm的标准 怎么最终 没有成为 行业的标准 呢…...
volatile,内存屏障
volatile的特性可见性: 对于其他线程是可见,假设线程1修改了volatile修饰的变量,那么线程2是可见的,并且是线程安全的重排序: 由于CPU执行的时候,指令在后面的会先执行,在指令层级的时候我们晓得volatile的特性后,我们就要去volatile是如何实现的,这个很重要!&#…...
【ESP 保姆级教程】玩转emqx MQTT篇① —— 系统主题、延迟发布、服务器配置预算、常见问题
忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-18 ❤️❤️ 本篇更新记录 2023-02-18 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…...
第48讲:SQL优化之ORDER BY排序查询的优化
文章目录1.ORDEY BY排序查询优化方面的概念2.ORDER BY排序的优化原则3.ORDER BY排序优化的案例3.1.准备排序优化的表以及索引3.2.同时对nl和lxfs字段使用升序排序3.3.同时对nl和lxfs字段使用降序排序3.4.排序时调整联合索引中字段的位置顺序3.5.排序时一个字段使用升序一个字段…...
[Datawhale][CS224W]图机器学习(三)
目录一、简介与准备二、教程2.1 下载安装2.2 创建图2.2.1 常用图创建(自定义图创建)1.创建图对象2.添加图节点3.创建连接2.2.2 经典图结构1.全连接无向图2.全连接有向图3.环状图4.梯状图5.线性串珠图6.星状图7.轮辐图8.二项树2.2.3 栅格图1.二维矩形栅格…...
2023版最新最强大数据面试宝典
此套面试题来自于各大厂的真实面试题及常问的知识点,如果能理解吃透这些问题,你的大数据能力将会大大提升,进入大厂指日可待!目前已经更新到第4版,广受好评!复习大数据面试题,看这一套就够了&am…...
CSS 中的 BFC 是什么,有什么作用?
BFC,即“块级格式化上下文”(Block Formatting Context),是 CSS 中一个重要的概念,它指的是一个独立的渲染区域,让块级盒子在布局时遵循一些特定的规则。BFC 的存在使得我们可以更好地控制文档流࿰…...
总结在使用 Git 踩过的坑
问题一: 原因 git 有两种拉代码的方式,一个是 HTTP,另一个是 ssh。git 的 HTTP 底层是通过 curl 的。HTTP 底层基于 TCP,而 TCP 协议的实现是有缓冲区的。 所以这个报错大致意思就是说,连接已经关闭,但是此时有未处理…...
从 HTTP 到 gRPC:APISIX 中 etcd 操作的迁移之路
罗泽轩,API7.ai 技术专家/技术工程师,Apache APISIX PMC 成员。 原文链接 Apache APISIX 现有基于 HTTP 的 etcd 操作的局限性 etcd 在 2.x 版本的时候,对外暴露的是 HTTP 1 (以下简称 HTTP)的接口。etcd 升级到 3.x…...
【C语言每日一题】——倒置字符串
【C语言每日一题】——倒置字符串😎前言🙌倒置字符串🙌总结撒花💞😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上吧!!! 😊作者简…...
外包商网站怎么做/百度识图扫一扫入口
开发需求 微信小程序已经是非常火了,而且学习也比较容易,但是对于初学者来说还是一件比较伤脑筋的事,接下来给大家分享一下小程序搜索的思路。 流程 1、表单(输入框、提交按钮、提交的name值)2、接收表单数据(js获取表…...
网站在线聊天源代码/怎么seo快速排名
信息技术教学计划及学情分析信息技术教学计划及学情分析以计算机技术、微电子技术和通信技术为特征的现代信息技术,在社会各个领域得到了广泛应用,并且逐渐改变着人们的生活方式、工作与学习方式.开展以提升学生信息素养和信息技术操作能力为主要目标的信息技术教育,正是全面推…...
殡葬网站建设/whois查询
JEPF软件快速开发平台学习心得之请假单功能的完成(一)首先我也是点一次接触这个软件快速开发平台,我在学习这个平台的同时简单记录下我对这个平台是如何一步步熟悉或者是上手的,也有简单的一点总结和学习心得,希望对你…...
基于h5的企业网站建设/快速将网站seo
原标题:C语言编程100题(其三)来啦,快来接招大家好啊,我是小C,咱们又见面咯,前面的题目做的怎么样呢,今天又给大家送上新的题目了,快来签收吧!01题目:有一个已经排好序的数组。现输入…...
广东网站优化/网上广告宣传怎么做
前几天写了个ffmpeg版本,今天特意抽空改写个vlc版本,之前vlc播放视频后,被接管了不能识别到鼠标,需要重新编译vlc源码得到支持鼠标消息的版本。/*** vlc视频播放类 作者:feiyangqingyun(QQ:517216493) 2018-5-2* 1:多线程实时播放…...
做网站有什么用/卡点视频软件下载
在JAVA编程中,有这样一个问题:类A引用了类B,那么如果运行时没有类B,类A会不会调用成功,而不抛异常? 答案是,有可能运行成功,而不抛异常。 例子1: ClassA.java packag…...