河北seo推广平台,青岛seo公司,赚钱游戏,营销技巧在线观看前言
在 Verilog 中#xff0c;关键字#xff08;Keywords#xff09;和基数#xff08;Radix#xff09;是语言的重要组成部分#xff0c;它们有助于描述和定义硬件设计。上期分享了 Verilog 的基本使用#xff0c;以及数据类型、逻辑值和算数运算符的简单应用#x…前言
在 Verilog 中关键字Keywords和基数Radix是语言的重要组成部分它们有助于描述和定义硬件设计。上期分享了 Verilog 的基本使用以及数据类型、逻辑值和算数运算符的简单应用具体请看
Verilog中的数据类型、逻辑值以及算术运算符https://blog.csdn.net/weixin_65793170/article/details/141629702?spm1001.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²CInter-Integrated Circuit总线中作为数据线使用。
双向端口意味着这个信号线既可以被模块用作输入也可以用作输出。po_flag (output wire):
这是一个输出端口类型为 wire。
po_flag 代表一个输出标志信号可能是模块内部某些条件满足后产生的标志。
这个模块包含两个输入端口(时钟和复位)、一个双向端口(数据线)和一个输出端口(标志信号)。这种端口定义方式是Verilog中常见的描述电路的方式。
inputinput 关键字用于声明一个端口为输入端口用于接收来自外部模块或其他实例的数据。输入端口可以是 wire、reg 或其他类型的变量。inoutinout 关键字用于声明一个端口为双向端口双向端口既可以用作输入端口也可以用作输出端口。它们通常用于需要双向通信的场合例如 I²C 总线中的 SDA 信号线。双向端口通常是 wire 类型。outputoutput 关键字用于声明一个端口为输出端口输出端口用于将模块内部的数据发送给外部模块或其他实例。输出端口通常是 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;
定义一个位宽为 WIDTH4位的寄存器 count用于存储值。wire [WIDTH-1:0] out;
定义一个与寄存器 count 同样位宽的线网 out。assign out count;
定义一个持续赋值的逻辑它将右侧表达式的值赋给左侧的网线wire或信号。
这种赋值是连续的并且会在任何相关信号变化时自动更新。
这里使用 assign 将寄存器 count 的值赋给线网 out。
这个模块定义了一些参数和变量,并建立了一个简单的连接。这种模块结构可以作为更复杂电路的基础,通过实例化和连接多个这样的模块来构建更大的电路系统。当然这段代码并不涉及任何行为逻辑。
wire一种用于模拟硬件中的连线的数据类型用于表示组合逻辑中的连线或信号。reg一种用于存储状态的数据类型通常用于描述触发器存储元件的行为用于表示时序逻辑中的寄存器。parameterparameter 用于定义全局常量这些常量在整个模块中都是可见的并且可以在模块实例化时通过实例化语句传递不同的值。localparamlocalparam 用于定义局部常量这些常量仅在定义它的模块内部可见。
其中 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 8hFF; // 将寄存器 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 8hFF; // 将寄存器 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二进制数 例如8b10101010 解释这里8 表示位宽为 8 位b 表示这是二进制数10101010 是二进制值。 2八进制表示符 (o) 作用用于表示八进制数。 语法位宽o八进制数 例如8o52 解释这里8 表示位宽为 8 位o 表示这是八进制数52 是八进制数值。 3十进制表示符 (d) 作用用于表示十进制数。 语法位宽d十进制数 例如8d85 解释这里8 表示位宽为 8 位d 表示这是十进制数85 是十进制值。 4十六进制表示符 (h) 作用用于表示十六进制数。 语法位宽h十六进制数 例如8hAA 解释这里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 8b10101010; // 二进制表示8b 表示 8 位二进制octal_value 8o52; // 八进制表示8o 表示 8 位八进制decimal_value 8d85; // 十进制表示8d 表示 8 位十进制hex_value 8hAA; // 十六进制表示8h 表示 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 8b10101010; // 二进制表示8b 表示 8 位二进制octal_value 8o52; // 八进制表示8o 表示 8 位八进制decimal_value 8d85; // 十进制表示8d 表示 8 位十进制hex_value 8hAA; // 十六进制表示8h 表示 8 位十六进制end
这是一个初始化块initial它会在模块加载到仿真环境中时执行一次。
在这段代码中设置了四个寄存器的初始值
binary_value 被初始化为 8b10101010即二进制表示的 10101010对应的十进制值为 170。
octal_value 被初始化为 8o52即八进制表示的 52对应的十进制值为 42。
decimal_value 被初始化为 8d85即十进制表示的 85对应的十进制值为 85。
hex_value 被初始化为 8hAA即十六进制表示的 AA对应的十进制值为 170。
这些不同的表示方式只是在初始化时使用的数值前缀不同
最终存储在寄存器中的仍然是8位的二进制数。endmodule
同样这一行标志着模块 simple_example 的结束。 创作不易感觉有用就一键三连感谢(●◡●)