Verilog常数赋值、字符串、标识符

本文深入解析Verilog中整数与实数的赋值规则,包括符号位处理、位宽扩展机制、带符号数与负数的区别,以及实常数的隐式转换规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://bestfpga.blog.youkuaiyun.com/article/details/102604599
————————————————
版权声明:本文为优快云博主「FPGADesigner」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://bestfpga.blog.youkuaiyun.com/article/details/102604599
1.整数赋值

按照Verilog 2005的标准:0-9、a-f、z、x称作数字位(digit)
表示数字正负的’+‘和’-‘视作一元操作符(unary operator)
常说的二进制、八进制、十进制、十六进制称作数字的基(base)
其在Verilog中的表示’b’、‘o’、‘d’、'h’称作基格式(base format)字符;
表示常数的bit数称作
size
。Verilog使用到的字符都是不区分大小写的。

另外要明白二进制数本身的运算规则与一个数是signed还是unsigned、小数点在哪个位置没有任何关系,这些只是设计者人为的规定。但是在代码设计时,要标识清楚数据是signed或unsigned,目的有两个:(1).对设计者的提示;(2).一些操作符、IP核的数据端口,对数据是signed或unsigned的“身份”有要求。

如果一个数是负数(前面加了’-’),那么它必定采用的是二进制补码形式。

方式1

常数赋值有两种,一种为直接赋值(符号+一串数字位),采用这种方式赋值时,默认数据是sigend形式。如下面一个简单的示例:

在这里插入代码片
module test
(
    input clk,
    output reg [31:0] c
);

wire [31:0] a, b;

assign a = -595;
assign b = -10;

always @ (posedge clk)
    c <= a + b;

endmodule 

对两个带符号数做加法运算,结果仍然是带符号数,Vivado中仿真时,将Radix设置为Signed Decimal,可以看到变量C的结果为-605。

方式2

另一种则是常见的基常数赋值方法(符号+size+单引号+基格式字符+一串数字位),如"assign a = +16’d53;", 符号和size是可有可无的。

如果在基格式字符(b、o、d、h)前加上’s’,表示这是个带符号数signed;没有加’s’则表示是不带符号数unsigend。如果前面加了符号位“-”,会自动用二进制补码的形式。

如下面的简单示例:

在这里插入代码片`timescale 1ns / 1ps

module test
(
    input clk,
    output reg [31:0] c
);

wire [31:0] a, b;

assign a = -32'd595;   // 加上size,省去s
assign b = -'sd10;      // 省略size,加上s

always @ (posedge clk)
    c <= a + b;

endmodule 

仿真结果与第一个示例相同。

位宽扩展

这里先不讨论将低位宽的数据赋值给高位宽数据的问题,比如将12bit的a赋值给16bit的b。先讨论直接将低位宽的常数赋值给高位宽的数据时,位宽扩展遵循怎样的标准(不考虑x和z)。

以下面的测试代码为例,将12bit的常数赋值给16bit的数据:

在这里插入代码片wire [15:0] a = 12'd565;
wire [15:0] b = -12'd565;
wire [15:0] c = -12'sd565;
reg [15:0] d = -12'sd565;

仿真结果如下,分别展示了赋值结果的2进制和10进制:
在这里插入图片描述

对于正数,赋值结果为高位补0。**对于负数(二进制补码),无论是reg还是wire型、加s声明为带符号数或者不加s,结果都是高位补符号位。可见位宽扩展只与数据的正、负有关。**Verilog HDL的位宽扩展机制可以确保设计者安全、便捷地完成程序设计。

“负数”与“带符号数”的区别

由于负数必须需要符号’-'来规定,所以第一感觉就是将负数和带符号数二者等同。**其实两者并不完全相同,如果只加负号,不加s,虽然软件工具会将其用二进制补码表示,但仍不会将其当作带符号数signed看待。**看下面的示例代码:

在这里插入代码片
module test
(
    input clk,
    output reg [15:0] a,b,c,d
);

always @ (posedge clk) begin
    a <= -12 / 3;
    b <= -'sd12 / 3;
    c <= -'d12 / 3;
    d <= -4'sd12 / 3;
end

endmodule

仿真结果如下图:
在这里插入图片描述
对于a:在没有规定大小和基格式时,-12和3都视作带符号数,因此结果为正确的-4;

对于b:-'sd12使用字符’s’声明这是个带符号数,结果同样是正确的-4;

对于c:-'d12虽然声明这是个负数,但没有加-s,软件仍然不会将其视作带符号数,运算结果与预期不符;

具体分析:+12为00……1100,取反为11……0011(共32位),加1得11……0100,由于没有申明为负数,因此做除法时,软件将其视为无符号数‭4,294,967,284‬,除以3得1,431,655,761‬,二进制存储为‭101 0101 0101 0101 0101 0101 0101 0001‬,由于定义为16位,仅保留低16位0101 0101 0101 0001‬,即十进制21841

对于d:-4’sd12同时还指定了大小,但4’sd12已经超过了4bit带符号数的表示范围,它的值12(1100)实际意义上是-4(最高位符号位表示负数,二进制补码),前面再加’-'为正4,除以3,近似为整数后值为1。

2.实常数赋值

Verilog HDL本身是支持在代码中使用小数、科学计数法的,只不过赋值给整数型数据时,会发生隐式转换,转换为整数。看下面的示例:

在这里插入代码片
wire [15:0] a = 1e4;
wire [15:0] b = 12.1;
wire [15:0] c = 12.5;
reg [15:0] d = -12.5;

仿真结果如下:
在这里插入图片描述
数据a用科学计数法进行赋值。隐式转换的规则是:(1). 转换为最接近的整数;(2).中间值.5转换时,向远离0的方向进行。如数据c,12.5 => 13;数据d,-12.5 => -13。

### 变量赋值的语法及示例 #### 通用编程语言中的变量赋值 在大多数编程语言中,变量赋值是一种常见的操作,用于将某个值存储到内存位置以便后续使用。以下是几种常见编程语言中关于变量赋值的基础介绍。 --- #### Python 中的变量赋值 Python 支持多种方式来完成变量赋值。可以为单个变量赋值,也可以通过元组拆包的方式一次性分配多个变量[^1]。 ```python # 单个变量赋值 num = 10 # 多个变量相同的值 num1 = num2 = num3 = 10 # 不同值的多变量赋值(元组拆包) a, b = 10, 20 ``` 这种灵活性使得开发者能够快速定义和初始化多个变量。 --- #### SystemVerilog 中的阻塞与非阻塞赋值 SystemVerilog 提供了两种主要的赋值形式:**阻塞赋值 (`=`)** 和 **非阻塞赋值 (`<=`)**。这两种方法适用于不同的场景,在硬件描述语言中有重要意义[^2]。 - 阻塞赋值会在当前语句完成后立即更新目标变量的值。 - 非阻塞赋值会延迟至整个过程结束后再统一更新所有被赋值的目标变量。 示例如下: ```verilog // 阻塞赋值 always @ (posedge clk) begin data_out = data_in; // 当前时刻立刻生效 end // 非阻塞赋值 always @ (posedge clk) begin data_out <= data_in; // 延迟到时钟周期结束再更新 end ``` 理解两者的差异对于设计同步电路至关重要。 --- #### Rust 中的变量声明赋值 Rust 是一种强类型语言,其变量默认不可变,除非显式标记为可变(`mut`)。此外,Rust 还支持模式匹配以及复杂的结构化数据类型的绑定[^3]。 下面是一些典型的例子: ```rust // 默认情况下变量是不可变的 let x = 5; // 使用 mut 关键字创建可变变量 let mut y = 10; y += 5; // 元组解构 let (a, b) = (true, false); // 数组定义 let array: [i32; 5] = [1, 2, 3, 4, 5]; ``` 值得注意的是,Rust 的所有权机制会影响如何管理资源及其生命周期。 --- #### ABAP 中的数据声明赋值 ABAP 是 SAP 平台上的专用开发语言,它也提供了丰富的数据类型和支持复杂业务逻辑的能力。以下是如何在 ABAP 中进行变量声明赋值的一个简单实例[^4]: ```abap DATA: lv_string TYPE string, lv_integer TYPE i VALUE 10. lv_string = 'Hello, World!'. ``` 上述代码片段展示了字符串和整数类型的定义与初始值设置。 --- ### 总结 每种编程语言都有独特的风格和规则处理变量赋值问题。无论是动态还是静态类型的语言,掌握这些基础知识都是构建高效应用程序的前提条件之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值