FPGA第 9 篇,Verilog 中的关键字和基数
前言
在 Verilog 中,关键字(Keywords)和基数(Radix)是语言的重要组成部分,它们有助于描述和定义硬件设计。上期分享了 Verilog 的基本使用,以及数据类型、逻辑值和算数运算符的简单应用,具体,请看,
Verilog中的数据类型、逻辑值以及算术运算符https://blog.csdn.net/weixin_65793170/article/details/141629702?spm=1001.2014.3001.5501
掌握这些技能基础,我们可以高效地设计和验证 FPGA 电路,从而实现所需的数字系统功能。这里我们继续分享关于 Verilog 的关键字和基数的应用,记录一下
一. Verilog 关键字
关键字:在 Verilog 中,关键字是 Verilog 语言的特殊词汇,它们用于定义硬件描述和控制程序的结构。关键字在 Verilog 中具有特定的语法和语义,帮助描述硬件的行为和结构,不能用作标识符(如变量名、信号名等)。
1. 模块定义与实例化
(1)模块的开始和结束
module:模块开始
endmodule:模块结束
代码示例:
module simple_example ( // 模块开始,模块名称为simple_example // 端口列表// ......); // 模块内部的内容endmodule // 结束模块定义
这里使用 module 定义了一个名为 simple_example
模块,包含端口列表和模块内部逻辑,使用endmodule
结束模块定义。
module:
定义一个模块的开始(定义模块名),后面跟模块名称,一般与文件名相同。simple_example 开始了一个名为simple_example
的模块定义,simple_example
是模块的名字。endmodule:
定义一个模块的结束,表示模块定义的结束。
(2)模块的输入和输出
input:输入信号
output:输出信号
inuot:输入和输出
代码示例:
module simple_example (input wire sys_clk, // 输入时钟信号input wire sys_rst_n, // 输入复位信号(低电平有效) inout wire sda, // 双向数据线output wire po_flag // 输出标志信号
);
endmodule代码解析:
sys_clk (input wire):
这是一个输入端口,类型为 wire。
sys_clk 通常代表系统时钟信号,用于同步电路的操作。
时钟信号通常是一个周期性的方波信号。sys_rst_n (input wire):
这也是一个输入端口,类型为 wire。
sys_rst_n 代表系统复位信号,带下划线 _n 表明这是一个“非”信号,即低电平有效(active low)。
当 sys_rst_n 为低电平时,表示复位有效;高电平时,系统正常工作。sda (inout wire):
这是一个双向端口,类型为 wire。
sda 通常用于串行数据传输,例如在I²C(Inter-Integrated Circuit)总线中作为数据线使用。
双向端口意味着这个信号线既可以被模块用作输入也可以用作输出。po_flag (output wire):
这是一个输出端口,类型为 wire。
po_flag 代表一个输出标志信号,可能是模块内部某些条件满足后产生的标志。
这个模块包含两个输入端口(时钟和复位)、一个双向端口(数据线)和一个输出端口(标志信号)。这种端口定义方式是Verilog中常见的描述电路的方式。
input
:input
关键字用于声明一个端口为输入端口,用于接收来自外部模块或其他实例的数据。输入端口可以是wire
、reg
或其他类型的变量。inout
:inout
关键字用于声明一个端口为双向端口,双向端口既可以用作输入端口,也可以用作输出端口。它们通常用于需要双向通信的场合,例如 I²C 总线中的SDA
信号线。双向端口通常是wire
类型。output
:output
关键字用于声明一个端口为输出端口,输出端口用于将模块内部的数据发送给外部模块或其他实例。输出端口通常是wire
类型,但也可以是reg
类型。只有输入信号是不能生成输出信号的,所以要用到一些变量和参数,对输入信号进行处理。
2. 数据类型与信号
wire:线网型变量
reg:寄存器变量
parameter:全局常量
localparam:局部常量
代码示例:
module simple_example();parameter WIDTH = 4; // 定义参数 WIDTHlocalparam MAX_VALUE = 15; // 定义本地参数 MAX_VALUEreg [WIDTH-1:0] count; // 定义寄存器 countwire [WIDTH-1:0] out; // 定义线网 outassign out = count; // 将寄存器的值连接到线网endmodule代码解析:
parameter WIDTH = 4;
定义位宽为 4 的参数 WIDTH。在顶层文件,通过实例化,可以对参数进行修改。localparam MAX_VALUE = 15;
定义一个不可更改的本地参数 MAX_VALUE,其值为 15,只能在模块内部使用。reg [WIDTH-1:0] count;
定义一个位宽为 WIDTH(4位)的寄存器 count,用于存储值。wire [WIDTH-1:0] out;
定义一个与寄存器 count 同样位宽的线网 out。assign out = count;
定义一个持续赋值的逻辑,它将右侧表达式的值赋给左侧的网线(wire)或信号。
这种赋值是连续的,并且会在任何相关信号变化时自动更新。
这里使用 assign 将寄存器 count 的值赋给线网 out。
这个模块定义了一些参数和变量,并建立了一个简单的连接。这种模块结构可以作为更复杂电路的基础,通过实例化和连接多个这样的模块来构建更大的电路系统。当然这段代码并不涉及任何行为逻辑。
- wire:一种用于模拟硬件中的连线的数据类型,用于表示组合逻辑中的连线或信号。
- reg:一种用于存储状态的数据类型,通常用于描述触发器(存储元件)的行为,用于表示时序逻辑中的寄存器。
- parameter:parameter 用于定义全局常量,这些常量在整个模块中都是可见的,并且可以在模块实例化时通过实例化语句传递不同的值。
- localparam:localparam 用于定义局部常量,这些常量仅在定义它的模块内部可见。
其中 simple_example
这是模块的名称,没有输入或输出端口时,括号可以省略,可以写成以下
这样,请看
module simple_example;parameter WIDTH = 4; // 定义参数 WIDTHlocalparam MAX_VALUE = 15; // 定义本地参数 MAX_VALUEreg [WIDTH-1:0] count; // 定义寄存器 countwire [WIDTH-1:0] out; // 定义线网 outassign out = count; // 将寄存器的值连接到线网endmodule
注意这里的 simple_example 后没带括号,直接可以省略。
3. 赋值与操作
assign:持续赋值
initial:初始化信号
always:始终块(用于逻辑)
代码示例:
module simple_example();reg [7:0] data; // 定义8位寄存器wire [7:0] result; // 定义8位线网// 持续赋值,将寄存器值赋给线网assign result = data;// 初始化块,仿真开始时设置寄存器的初值initial begindata = 8'hFF; // 将寄存器 data 初始化为 255 (十六进制 FF)end// 始终块,根据时钟上升沿修改寄存器的值always @(posedge clk) begindata <= data + 1; // 每个时钟周期递增寄存器的值endendmodule代码解析:
module simple_example;
这一行定义了一个新的Verilog模块simple_example。reg [7:0] data; // 定义8位寄存器wire [7:0] result; // 定义8位线网
这两行定义了两个变量,一个是8位宽的寄存器data,另一个是8位宽的线网result。
寄存器用来存储数据,而线网则用于传递数据。assign result = data;
这行是一个连续赋值语句(continuous assignment),它把寄存器data的值赋给了线网result。
这意味着任何时候data的值发生变化,result也会立即反映出这个变化。initial begindata = 8'hFF; // 将寄存器 data 初始化为 255 (十六进制 FF)end
这是一个初始化块(initial block)。当模块被加载到仿真环境中时,这段代码会被执行一次。
在这里,data被初始化为255(十六进制FF)。always @(posedge clk) begindata <= data + 1; // 每个时钟周期递增寄存器的值end
这部分是一个敏感于时钟信号上升沿的always块。
每当检测到clk信号的上升沿时,寄存器data的值就会增加1。
这里使用的是阻塞赋值(<=),这是因为在时序逻辑中,
我们关心的是在一个时钟周期内完成赋值,而不是立即完成。endmodule
这一行标志着模块simple_example的结束。
这段代码定义了一个简单的模块simple_example
,它包含了一个8位的寄存器data
和一个8位的线网result
。这个模块的目的是演示如何在Verilog中定义寄存器和线网,并展示如何使用initial
和always
块来初始化和更新寄存器的值。
-
assign
: 用于持续赋值,将一个表达式的值分配给一个wire
类型的信号,常用于组合逻辑。 -
initial
: 定义初始块,在仿真开始时执行一次,用于初始化信号的值。 -
always
: 定义始终块,用于描述时序逻辑或组合逻辑,根据触发条件执行块中的代码。
4. 以上关键字整合
module:模块开始
endmodule:模块结束
input:输入信号
output:输出信号
inuot:输入和输出
wire:线网型变量
reg:寄存器变量
parameter:全局常量
localparam:局部常量
assign: 持续赋值
initial: 初始化信号
always: 始终块(用于逻辑)
等等
5. 关键字与数据类型
- Verilog HDL 中的关键字和数据类型不是同一个概念,并且它们之间存在一定的差异,尽管有时会有重叠的地方。
- 有一些标识符既是关键字也是数据类型,比如
wire
和reg
。在有些情况下,它们作为关键字时用于声明信号或变量,并且它们本身也指示了一种特定的数据类型。然而,像if
,else
,case
,begin
,end
这样的关键字则不是数据类型。- 关键字和数据类型虽然有交集,但它们并不是同一个概念。关键字主要用于定义Verilog程序的语法结构,而数据类型则是用于定义变量的属性。在编写Verilog代码时,正确区分和使用这两者是非常重要的。
二. Verilog 基数
1. 基数介绍
基数:在 Verilog 中,基数用于表示数值的进制方式,有助于更清晰地表达数字的意义。常见的基数包括二进制、八进制、十进制和十六进制,它们在代码中的表示语法各不相同。这种灵活性使得我们能够直观且方便地表达数值,从而提高代码的可读性和可维护性。
2. 基数分类
(1)二进制表示符 (b)
作用:用于表示二进制数。
语法:<位宽>'b<二进制数>
例如:8'b10101010
解释:这里,8 表示位宽为 8 位,b 表示这是二进制数,10101010 是二进制值。
(2)八进制表示符 (o)
作用:用于表示八进制数。
语法:<位宽>'o<八进制数>
例如:8'o52解释:这里,
8
表示位宽为 8 位,o 表示这是八进制数,52 是八进制数值。
(3)十进制表示符 (d)
作用:用于表示十进制数。
语法:<位宽>'d<十进制数>
例如:8'd85解释:这里,
8
表示位宽为 8 位,d
表示这是十进制数,85
是十进制值。
(4)十六进制表示符 (h)
作用:用于表示十六进制数。
语法:<位宽>'h<十六进制数>
例如:8'hAA解释:这里,
8
表示位宽为 8 位,h
表示这是十六进制数,AA
是十六进制值(即二进制为10101010
)。
(5)基数小结
b
: 二进制o
: 八进制d
: 十进制h
: 十六进制
3. 基数使用
(1)示例代码
module simple_example;reg [7:0] binary_value; // 二进制值reg [7:0] octal_value; // 八进制值reg [7:0] decimal_value; // 十进制值reg [7:0] hex_value; // 十六进制值initial beginbinary_value = 8'b10101010; // 二进制表示,8'b 表示 8 位二进制octal_value = 8'o52; // 八进制表示,8'o 表示 8 位八进制decimal_value = 8'd85; // 十进制表示,8'd 表示 8 位十进制hex_value = 8'hAA; // 十六进制表示,8'h 表示 8 位十六进制endendmodule
这段代码定义了一个名为 simple_example
的模块,其中包含了四个8位宽的寄存器,分别用于存储二进制、八进制、十进制和十六进制的值。模块中还包含了一个初始化块,用于设置这些寄存器的初始值。
(2)详细解析
module simple_example;
同样定义了一个新的Verilog模块 simple_example。reg [7:0] binary_value; // 二进制值reg [7:0] octal_value; // 八进制值reg [7:0] decimal_value; // 十进制值reg [7:0] hex_value; // 十六进制值
这四行定义了四个8位宽的寄存器:
binary_value 用于存储一个8位的二进制值。
octal_value 用于存储一个8位的八进制值。
decimal_value 用于存储一个8位的十进制值。
hex_value 用于存储一个8位的十六进制值。
尽管这些名称暗示了它们存储的数值类型,但实际上它们都是8位的二进制数。
不同的表示方式只是在初始化时使用的数值前缀不同。initial beginbinary_value = 8'b10101010; // 二进制表示,8'b 表示 8 位二进制octal_value = 8'o52; // 八进制表示,8'o 表示 8 位八进制decimal_value = 8'd85; // 十进制表示,8'd 表示 8 位十进制hex_value = 8'hAA; // 十六进制表示,8'h 表示 8 位十六进制end
这是一个初始化块(initial),它会在模块加载到仿真环境中时执行一次。
在这段代码中,设置了四个寄存器的初始值:
binary_value 被初始化为 8'b10101010,即二进制表示的 10101010,对应的十进制值为 170。
octal_value 被初始化为 8'o52,即八进制表示的 52,对应的十进制值为 42。
decimal_value 被初始化为 8'd85,即十进制表示的 85,对应的十进制值为 85。
hex_value 被初始化为 8'hAA,即十六进制表示的 AA,对应的十进制值为 170。
这些不同的表示方式只是在初始化时使用的数值前缀不同,
最终存储在寄存器中的仍然是8位的二进制数。endmodule
同样这一行标志着模块 simple_example 的结束。
创作不易,感觉有用,就一键三连,感谢(●'◡'●)
相关文章:

FPGA第 9 篇,Verilog 中的关键字和基数
前言 在 Verilog 中,关键字(Keywords)和基数(Radix)是语言的重要组成部分,它们有助于描述和定义硬件设计。上期分享了 Verilog 的基本使用,以及数据类型、逻辑值和算数运算符的简单应用&#x…...

什么是单元测试?怎么做?
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。至于“单元”的大小…...

论文复现--基于LeNet网络结构的数字识别
前言 一直就听说学习深度学习无非就是看论文,然后复现,不断循环,这段时间也看了好几篇论文(虽然都是简单的),但是对于我一个人自学,复现成功,我感觉还是挺开心的 本人初学看论文的思路:聚焦网络…...

Vue3 响应式工具函数isRef()、unref()、isReactive()、isReadonly()、isProxy()
isRef() isRef():检查某个值是否为 ref。 isRef函数接收一个参数,即要判断的值。如果该参数是由ref创建的响应式对象,则返回true;否则,返回false。 import { ref, isRef } from vue const normalValue 这是一个普通…...

数据结构之简单选择排序介绍与举例
简单选择排序 简单选择排序是一种排序算法,其基本思想是:通过n-i次关键字间的比较,从n-i1个记录中选出关键字最小的记录,并和第i个记录交换之。 举例: 给定数组 [64, 25, 12, 22, 11],进行简单选择排序。…...

九、Redis 的实际使用与Redis的设计
一、多级缓存架构 在线上系统中,一定不会单纯的只部署一个Redis集群,而是使用Redis结合其他的多级缓存应用进行架构。 使用多级缓存架构的优点就是可以使不同类型的数据分布在不同的应用中,比如redis的热点key可以存储到nginx本地缓存、服务…...

乔拓云模板助力,微信小程序快速上线无需愁备案
想要快速打造并上线自己的微信小程序吗?乔拓云平台是您的不二之选!无需担心复杂的备案流程,乔拓云提供免费服务,远程协助您轻松完成微信小程序的备案工作。 只需简单几步,您的小程序就能闪亮登场:首先&…...

Android命令行查看CPU频率和温度
在 Android 设备上,你可以通过命令行工具 adb 来查看 CPU 温度和 CPU 频率,并确定是否有降频情况。以下是具体步骤: 1. 查看 CPU 频率 你可以使用以下命令来查看 CPU 各个核心的当前频率: adb shell cat /sys/devices/system/c…...

力扣: 翻转字符串里的单词
文章目录 需求分析代码结尾 需求 给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意:输入字符…...

Wophp靶场寻找漏洞练习
1.命令执行漏洞 打开网站划到最下,此处的输入框存在任意命令执行漏洞 输入命令whoami 2.SQL注入 搜索框存在SQL注入,类型为整数型 最终结果可以找到管理员账户和密码 3.任意文件上传漏洞 在进入管理员后台后,上传木马文件 访问该文件&…...

国内智能运维厂商月度动态 202408
作为市场人员,虽然也添加了各类行业媒体、同行厂商的关注,但被同事问起业内动向时,常常也是记忆模糊、拍破脑袋也说不完整一件事。 所以找机会翻看了一下各大厂商的公号,先做个简单的8月汇总。 格式暂时是这样的: 整…...

C++ 左值与右值浅谈
左值与右值 序言概念左值和右值的划分理解右值引用常量左值引用与右值引用 移动语义引用折叠完美转发 参考资料 序言 虽然平常都算是了解左值,右值的用法,但是好记性不如烂笔头,记下来供大家评鉴,有错改错,有善赞善&a…...

oracle 如何查死锁
在Oracle中查看死锁通常涉及查询数据字典视图和动态性能视图。以下是一个基本的查询示例,用于检测和显示最近的死锁: SELECT dd.inst_id, dd.name, o.object_id, o.object_type, s.sid, s.serial#, s.username, p.spid, s.program,d.xidusn,d.xidslot,d…...

如何编写ChatGPT提示词
为ChatGPT编写有效的提示需要实施几个关键策略,以使文本到文本生成 AI 工具产生所需的输出。您可以使用 ChatGPT 提示(也称为 ChatGPT 命令)来增强您的工作或提高您在各个行业的表现。例如,营销人员可以提示 ChatGPT 为社交媒体帖…...

java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
项目简介 智能无人仓库管理实现了以下功能: 基于Spring Boot智能无人仓库管理的主要使用者分为: 管理员的功能有:员工信息的查询管理,可以删除员工信息、修改员工信息、新增员工信息 💕💕作者:…...

大厂前端常见的笔试题目
https://zhuanlan.zhihu.com/p/488383397前端面试手写题目总结-CSDN博客 大厂前端面试中常见的手写代码题目涵盖了多个方面,包括但不限于算法、数据结构、JavaScript 基础知识、DOM 操作、异步编程等。以下是一些常见的手写代码题目及其简要说明: 1. 排…...

网络插件 Cilium 更换 Calico
网络插件 Cilium 更换 Calico 集群使用 submariner ,通过网络检测发现 Cilium 插件可能兼容性不太好 subctl diagnose allCilium 彻底卸载 helm uninstall cilium -n kube-system# 检查集群中的所有 CNI 插件(集群的每个节点都需要删除) s…...

SpringSecurity原理解析(二):认证流程
1、SpringSecurity认证流程包含哪几个子流程? 1)账号验证 2)密码验证 3)记住我—>Cookie记录 4)登录成功—>页面跳转 2、UsernamePasswordAuthenticationFilter 在SpringSecurity中处理认证逻辑是在UsernamePas…...

数据中台 | 数据资源管理平台介绍
01 产品概述 数据资源的盘查、集成、存储、组织、共享等全方位管理能力,无论对于企业的数字化转型,还是对企业数据资产的开发、运营、交易及入表,都具有极为关键的作用。今天,小兵就来为大家介绍我们自研数据智能平台中的核心产品…...

智慧环保平台建设方案
智慧环保平台建设方案摘要 政策导向与建设背景 背景:全国生态环境保护大会提出坚决打好污染防治攻坚战,推动生态文明建设,目标是在2035年实现生态环境质量根本好转。构建生态文明体系,包括生态文化、生态经济、目标责任、生态文明…...

SpringMVC映射请求;SpringMVC返回值类型;SpringMVC参数绑定;
一,SpringMVC映射请求 SpringMVC 使用 RequestMapping 注解为控制器指定可以处理哪些URL请求 1.1RequestMapping修饰类 注解RequestMapping修饰类,提供初步的请求映射信息,相对于WEB应用的跟目录。 注: 如果在类名前࿰…...

【第28章】Spring Cloud之Sentinel注解支持
文章目录 前言一、注解埋点支持二、SentinelResource 注解三、实战1. 准备2. 纯资源定义3. 添加资源配置 四、熔断(fallback)1. 业务代码1.1 Controller1.2 Service1.3 ServiceImpl 2. 熔断配置3. 熔断测试 总结 前言 上一章我们已经完成了对Sentinel的适配工作,这…...

鼎捷新一代PLM 荣膺维科杯 “2023年度行业优秀产品奖”
近日,由中国高科技行业门户OFweek维科网主办的“全数会2024(第五届)中国智能制造数字化转型大会暨维科杯工业自动化及数字化行业年度评选颁奖典礼”在深圳隆重举办。这不仅是中国工业自动化及数字化行业的一大品牌盛会,亦是高科技…...

如何升级用 Helm 安装的极狐GitLab Runner?
本分分享如何对 Helm 安装的 Runner 进行升级。整个过程分为三步:1、确定 Runner 最新版本或者想要升级的版本是否存在;2、用 Helm upgrade 命令进行升级;3、升级确认。 极狐GitLab 为 GitLab 的中国发行版,中文版本对中国用户更…...
08 vue3之认识bem架构及less sass 和scoped
bem架构 他是一种css架构 oocss 实现的一种 (面向对象css) ,BEM实际上是block、element、modifier的缩写,分别为块层、元素层、修饰符层,element UI 也使用的是这种架构 1. BEM架构 1. 介绍 1. BEM是Block Element M…...

静态库的制作
静态库是一组对象文件的集合,它们在编译时被链接到可执行文件中。这意味着,静态库中的代码会被复制到每个使用它的程序中,因此静态库不需要在程序运行时被单独加载。制作静态库可以帮助你将常用的代码模块化、重用,简化开发过程。…...

PHP在现代Web开发中的高效应用与最佳实践
PHP在现代Web开发中的高效应用与最佳实践 在快速迭代的Web开发领域,PHP作为一门历史悠久且广泛应用的服务器端脚本语言,始终保持着其独特的魅力和强大的生命力。从简单的动态网页到复杂的企业级应用,PHP凭借其易学性、丰富的库支持和广泛的社…...

大数据-134 - ClickHouse 集群三节点 安装配置启动
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

2024网络安全人才实战能力白皮书安全测试评估篇
9月10日,国内首个聚焦“安全测试评估”的白皮书——《网络安全人才实战能力白皮书-安全测试评估篇》(以下简称“白皮书”)在国家网络安全宣传周正式发布。 作为《网络安全人才实战能力白皮书》的第三篇章,本次白皮书聚焦“安全测…...

[项目][WebServer][解析错误处理]详细讲解
可为每种情况都确实对应一个状态码,当发生错误时,跳转到对应的html页面即可但是为了代码的复用性,可以将所有的错误情况都归置处理 #define SEP ": " #define LINE_END "\r\n" #define WEB_ROOT "wwwroot" #…...