FPGA第 9 篇,Verilog 中的关键字和基数

news2024/12/24 9:38:57

前言

在 Verilog 中,关键字(Keywords)和基数(Radix)是语言的重要组成部分,它们有助于描述和定义硬件设计。上期分享了 Verilog 的基本使用,以及数据类型、逻辑值和算数运算符的简单应用,掌握这些技能基础,我们可以高效地设计和验证 FPGA 电路,从而实现所需的数字系统功能。上期介绍了 Verilog 中的数据类型、逻辑值以及算术运算符,具体,请看上篇,

Verilog中的数据类型、逻辑值以及算术运算符icon-default.png?t=O83Ahttps://blog.csdn.net/weixin_65793170/article/details/141629702?spm=1001.2014.3001.5501

这里我们继续分享关于 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中常见的描述电路的方式。

  • inputinput 关键字用于声明一个端口为输入端口,用于接收来自外部模块或其他实例的数据。输入端口可以是 wirereg 或其他类型的变量。
  • inoutinout 关键字用于声明一个端口为双向端口,双向端口既可以用作输入端口,也可以用作输出端口。它们通常用于需要双向通信的场合,例如 I²C 总线中的 SDA 信号线。双向端口通常是 wire 类型。
  • outputoutput 关键字用于声明一个端口为输出端口,输出端口用于将模块内部的数据发送给外部模块或其他实例。输出端口通常是 wire 类型,但也可以是 reg 类型。只有输入信号是不能生成输出信号的,所以要用到一些变量和参数,对输入信号进行处理。

2. 数据类型与信号

wire:线网型变量

reg:寄存器变量

parameter:全局常量

localparam:局部常量

代码示例:

module simple_example();

    parameter WIDTH = 4;  // 定义参数 WIDTH
    localparam MAX_VALUE = 15;  // 定义本地参数 MAX_VALUE

    reg [WIDTH-1:0] count;  // 定义寄存器 count
    wire [WIDTH-1:0] out;  // 定义线网 out

    assign 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;  // 定义参数 WIDTH
    localparam MAX_VALUE = 15;  // 定义本地参数 MAX_VALUE

    reg [WIDTH-1:0] count;  // 定义寄存器 count
    wire [WIDTH-1:0] out;  // 定义线网 out

    assign 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 begin
        data = 8'hFF;  // 将寄存器 data 初始化为 255 (十六进制 FF)
    end

    // 始终块,根据时钟上升沿修改寄存器的值
    always @(posedge clk) begin
        data <= data + 1;  // 每个时钟周期递增寄存器的值
    end

endmodule



代码解析:
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 begin
        data = 8'hFF;  // 将寄存器 data 初始化为 255 (十六进制 FF)
    end
这是一个初始化块(initial block)。当模块被加载到仿真环境中时,这段代码会被执行一次。
在这里,data被初始化为255(十六进制FF)。

    always @(posedge clk) begin
        data <= data + 1;  // 每个时钟周期递增寄存器的值
    end
这部分是一个敏感于时钟信号上升沿的always块。
每当检测到clk信号的上升沿时,寄存器data的值就会增加1。
这里使用的是阻塞赋值(<=),这是因为在时序逻辑中,
我们关心的是在一个时钟周期内完成赋值,而不是立即完成。

endmodule
这一行标志着模块simple_example的结束。

这段代码定义了一个简单的模块simple_example,它包含了一个8位的寄存器data和一个8位的线网result。这个模块的目的是演示如何在Verilog中定义寄存器和线网,并展示如何使用initialalways块来初始化和更新寄存器的值。

  • assign: 用于持续赋值,将一个表达式的值分配给一个 wire 类型的信号,常用于组合逻辑。

  • initial: 定义初始块,在仿真开始时执行一次,用于初始化信号的值。

  • always: 定义始终块,用于描述时序逻辑或组合逻辑,根据触发条件执行块中的代码。


4. 以上关键字整合

module:模块开始

endmodule:模块结束

input:输入信号

output:输出信号

inuot:输入和输出

wire:线网型变量

reg:寄存器变量

parameter:全局常量

localparam:局部常量

assign: 持续赋值

initial: 初始化信号

always: 始终块(用于逻辑)

等等


5. 关键字与数据类型

  1. Verilog HDL 中的关键字和数据类型不是同一个概念,并且它们之间存在一定的差异,尽管有时会有重叠的地方。
  2. 有一些标识符既是关键字也是数据类型,比如 wirereg。在有些情况下,它们作为关键字时用于声明信号或变量,并且它们本身也指示了一种特定的数据类型。然而,像 if, else, case, begin, end 这样的关键字则不是数据类型。
  3. 关键字和数据类型虽然有交集,但它们并不是同一个概念。关键字主要用于定义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 begin
        binary_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

endmodule

这段代码定义了一个名为 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 begin
        binary_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 的结束。

创作不易,感觉有用,就一键三连,感谢(●'◡'●)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2107870.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器安装pytorch-阿里云-centos7

原文阅读&#xff1a;【巨人肩膀社区专栏分享】服务器安装pytorch-阿里云-centos7 1、创建一个虚拟环境 conda create -n pytorch python3.10 安装成功&#xff1a; &#xfeff; &#xfeff;&#xfeff; 但是使用上面的命令会失败&#xff08;疑问&#xff1f;&#xf…

Apache Guacamole 安装及配置VNC远程桌面控制

文章目录 官网简介支持多种协议无插件浏览器访问配置和管理应用场景 Podman 部署 Apache Guacamole拉取 docker 镜像docker-compose.yml部署 PostgreSQL生成 initdb.sql 脚本部署 guacamole Guacamole 基本用法配置 VNC 连接 Mac 电脑开启自带的 VNC 服务 官网 https://guacam…

编程式路由跳转

点击左侧的导航栏&#xff0c;会跳转到相应的页面。可以在导航栏上定义一个点击事件&#xff0c;在vue-router中解构useRouter,把useRouter赋给router,使用***router.push()***就可以实现编程式路由跳转。 路由跳转有:to,push,replace push模式在浏览器上有历史记录&#xff…

【华为】测试工程师面试题汇总,你可知道华为的高薪技术岗有多香~

华为一直是求职者重点投递的热门企业&#xff0c;面对丰厚的薪资福利&#xff0c;无数985、211的学子挤破脑袋都想占据一席之地。 华为2021年发放工资、薪金及其他福利方面的费用达1371亿元人民币&#xff0c;按华为19.5万员工计算&#xff0c;华为员工人均年薪为70.3万&#…

[每日一题]3174. 清除数字

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

Vue Router 入门指南:基础配置、路由守卫与动态路由

Vue Router 入门指南&#xff1a;基础配置、路由守卫与动态路由 简介&#xff1a; Vue Router 是 Vue.js 官方的路由管理工具&#xff0c;用于在 Vue 应用中实现页面导航。掌握 Vue Router 的基本配置、路由守卫以及动态路由和懒加载是构建复杂 Vue 应用的基础。本文将详细介绍…

web前端-HTML标签

一、HTML语法规范 1.基本语法概述 &#xff08;1&#xff09;HTML标签是由尖括号包围的关键词&#xff0c;例如<html> &#xff08;2&#xff09;HTML标签通常是成对出现的,例始<html>和</html>&#xff0c;我们称为双标签。标签对中的第一个标签是开始标…

STM32(一)简介

一、stm32简介 1.外设接口 通过程序配置外设来完成功能 2.系统结构 3.引脚定义 4.启动配置 5.最小系统电路

解决:axios 请求头url传参数组时发生400错误

一、前言 axios封装的网络请求&#xff0c;url传参时&#xff0c;数组作为参数传递&#xff0c;发生400错误请求时数组参数转url会保留 [] 二、原因 RFC3986&#xff1a;除了 数字 字母 -_.~ 不会被转义&#xff0c;其他字符都会被以百分号&#xff08;%&#xff09;后跟两位…

QT:动态库与静态库的生成和使用

目录 一.动态库和静态库 1.动态链接&#xff08;Dynamic Linking&#xff09; 2.静态链接&#xff08;Static Linking&#xff09; 3.选择依据 二.库的创建 1.新建文件和项目中&#xff0c;选择Library中C库 2.新建一个名为libtest库 3.打印一个qDebug&#xff0c;用于…

PCA数据降维技术详解

在数据分析和机器学习的世界里&#xff0c;维度灾难是一个不可忽视的问题。随着数据维度的增加&#xff0c;计算量急剧上升&#xff0c;模型复杂度变高&#xff0c;同时可能引入噪声和冗余信息&#xff0c;影响模型的性能和解释性。主成分分析&#xff08;Principal Component …

第六篇——黄金分割:毕达哥拉斯如何连接数学和美学?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 人眼看到的美的东西&#xff0c;都可以从数学这个抽象的学科中得到明确的…

网页打印模板解析源码--SAAS本地化及未来之窗行业应用跨平台架构

一、打印模板解析 /* ///cyberwin_offline_database_printtemp.js未来之窗打印模板解析技术 2024-09 */ class CyberWin_Database_printtemp_KV {constructor() {this.data {};this.line_count 0 ;}解析(数据) {// this.data[key] value;this.line_count 0 ;this.data {}…

生日(仅粉丝可见,生日是9月6日,提前一天发的)

祝我自己生日快乐&#xff01; 感谢大家的陪伴与支持&#xff0c;以后我会努力做作品的&#xff01; &#xff08;累谁也不能累自己&#xff0c;所以我打算放3天假&#xff0c;反正延迟开学&#xff0c;先玩了来再去上学&#xff01;&#xff09;

数据库超时排查

背景&#xff1a; 项目是用的springboot&#xff0c;连接池用的是hikaricp&#xff0c;且数据库连接做了LB配置&#xff0c;之前就是经常会有数据库出现问题&#xff0c;专家给到的解决方案。 数据连接io超时报错&#xff0c;排查了当时数据库各项指标都无显示异常&#xff0c;…

基于SA-BP模拟退火算法优化BP神经网络实现数据预测Python实现

在数据分析和机器学习领域&#xff0c;时间序列预测和多输入单输出系统的预测是重要且复杂的问题。传统的BP&#xff08;反向传播&#xff09;神经网络虽然具有强大的非线性函数逼近能力&#xff0c;但在处理这些问题时容易陷入局部极小值、训练速度慢以及过拟合等问题。为了克…

【读书笔记-《30天自制操作系统》-15】Day16

本篇内容继续多任务的讲解。上一篇中实现了两个任务之间的自动切换&#xff0c;但还不够通用&#xff0c;这里将其优化为多个任务之间的切换。接着引入了任务休眠的概念与休眠的程序实现。最后介绍了任务的优先级&#xff0c;一种用切换时间的长短来衡量&#xff0c;一种用Task…

【Qt】文件对话框QFileDialog

文件对话框QFileDialog ⽂件对话框⽤于应⽤程序中需要打开⼀个外部⽂件或需要将当前内容存储到指定的外部⽂件。 通过QFileDialog 可以选择一个文件&#xff0c;能够获取到这个文件的路径&#xff0c;打开文件/保存文件。 常⽤⽅法介绍&#xff1a; 1、打开⽂件&#xff08;⼀…

【高中生讲机器学习】17. 讲人话的主成分分析,它来了!(上篇)

创建时间&#xff1a;2024-08-13 首发时间&#xff1a;2024-09-05 最后编辑时间&#xff1a;2024-09-05 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名准高一学生&#xff0c;热爱…

Redis 集群高可用详解及配置

关型数据库 关系型数据库&#xff1a; 是建立在关系模型基础上的数据库&#xff0c;其借助于集合代数等数学概念和方法来处理数据库中的数据 主流的 MySQL、Oracle、MS SQL Server 和 DB2 都属于这类传统数据库 关型数据库的优缺点 特点&#xff1a; 1、数据关系模型基于关系…