【芝士】VLSI第六讲:Verilog HDL向量、存储、运算符
向量是寄存器和总线的形态,存储器是向量的阵列延伸,而运算符则是真正干活儿的"动作"。把它们合在一起看,写起稍微复杂一点的电路就顺手多了。值得一提的是,写完主题内容之后,让AI扩展一下,并进行排版,确实比纯手敲好不少。可惜这个网站貌似不支持markdown格式,不然能更方便一点
================================================================
一、标量与向量
================================================================
宽度为 1 位的变量叫"标量",声明里没指定位宽就是默认标量:
wire a; // a 是标量(1 位)
regclk; // clk 是标量(1 位)
宽度大于 1 位的变量叫"向量",wire 和 reg 都适用。向量宽度用方括号指定:
wire bus; // 4 位总线,左边是最高位
reg data; // 8 位寄存器
注意方括号里 这种写法: 是最高有效位(MSB), 是最低有效位(LSB)。也可以写成 ,最低位在前面,只是写法不同,用的时候别把索引搞混。
================================================================
二、位选择和域选择
================================================================
在表达式里可以选中向量中的某一位或者连续几位,分别叫"位选择"和"域选择",是 Verilog 里非常常用的操作。
· 位选择:选中向量里的某一位
· 域选择:选中向量里相邻的连续几位
// 假设有 reg mybyte;
A = mybyte; // 位选择:取第 2 位
B = mybyte; // 域选择:取第 3 到第 1 位
再看一个实际场景:
reg a, b;
reg c;
reg d;
d = a & b; // 位选择,分别取最高位做与运算
c = a + b; // 域选择,高 4 位和低 4 位相加
位选择和域选择也可以出现在赋值语句的左边:
wire out;
wire in;
assign out = in; // 把 out 的第 2 到 5 位赋成 in 的值
这段代码等效于:
assign out = in;
assign out = in;
assign out = in;
assign out = in;
[注意] 顺带提一下 vectored 关键字。如果声明成 wire vectored databus;,就表示这是个"向量类向量",这种情况下不能进行位选和域选;不加这个关键字(默认是标量类向量)就都可以选。一般情况下用默认的就好,vectored 只在特殊场合用。
================================================================
三、存储器(Memory)
================================================================
存储器可以看作一个二维的向量,或者说是由一组寄存器构成的阵列。简单理解:
n 个相同宽度的 reg 向量排成一排,就是一个存储器。
声明语法:
reg 存储名;
一个存储器声明包含两个维度的信息:
· 位宽(字长):每个存储单元有多宽,比如每个单元 8 bit
· 容量(深度):一共有多少个这样的单元,比如 64 个
举个例子:
reg mymem ;
// 这是一个存储器,名字叫 mymem
// 每个单元 8 位宽(字长 8),一共有 64 个单元(容量 64)
// 可以理解为:64 个 8 位寄存器排成的阵列
再举几个:
reg Amem ; // 64 个单元,每个单元 4 位
reg Bmem ; //5 个单元,每个单元 1 位(不写位宽默认 1 位)
为了让尺寸好修改,可以用 parameter 参数化:
parameter width = 8, memsize = 1024;
reg mymem ;
// 定义了字长 8 bit、容量 1024 的存储器
================================================================
四、存储器使用的注意事项
================================================================
存储器有几个限制一定不能踩,否则综合会报错。
4.1只能对存储器的某一个单元整体赋值
reg mymem ; // 定义
mymem= 8'b10001001; // 合法:给第 8 个单元赋值
mymem = 65; // 合法:十进制 65 赋给第 25 个单元
mymem = 8'b10001001; // 非法!不能一次赋整个存储器
4.2不允许对存储器进行位选择和域选择
mymem; // 非法!存储器单元不能再拆位
mymem; // 非法!
================================================================
五、寄存器与存储器的区别
================================================================
这个区别很多初学者都会搞混,专门列一下:
reg rega; // 这是一个 n 位的寄存器
reg mema ; // 这是一个由 n 个 1 位寄存器构成的存储器
赋值的区别:
rega = 1'b1; // 合法:对寄存器的某一位赋值
mema = 1'b1; // 合法:对存储器的某个单元赋值
rega = 8'b01011000; // 合法:对寄存器整体赋值
mema = 8'b01011000; // 非法!不允许对存储器的所有单元一次性赋值
简单记:一个 n 位的寄存器可以在一条语句里整体赋值,但一个完整的存储器是不行的,必须一个单元一个单元来。
================================================================
六、Verilog 运算符总览
================================================================
把向量和存储器讲完之后,接下来就是真正干活儿的运算符。Verilog 的运算符可以从两个维度来看:
· 按操作数个数分:单目、双目、三目
· 按功能分:算术、逻辑、位运算、关系、等式、缩位、移位、条件、位拼接
下面按功能分类一个个过一遍,尽量每种都配上例子。
6.1按操作数个数分类
· 单目运算符:只带一个操作数,比如~a
· 双目运算符:带两个操作数,比如a + b
· 三目运算符:带三个操作数(Verilog 里只有 ?:),比如sel ? a : b
6.2算术运算符(Arithmetic)
· + 加
· - 减
· * 乘
· / 除
· % 求模(取余)
这些和 C 语言基本一样,需要注意除法和取模在硬件里实现起来比较占资源。
6.3逻辑运算符(Logical)
· && 逻辑与
· || 逻辑或
· ! 逻辑非
注意这里说的是"逻辑"运算。如果操作数不止一位,要把整个操作数当作一个整体来看:全 0 才算逻辑 0,只要有一位是 1 就整体看作逻辑 1。最后的结果都是 1 位的值。
举个例子,A=4'b0000; B=4'b0101; C=4'b0011; D=4'b0000;
!A = 1 // A 全 0,整体是逻辑 0,取非就是 1
!B = 0 // B 不是全 0,整体是逻辑 1,取非就是 0
A&&B= 0 // A 是逻辑 0,与运算结果为 0
B&&C= 1 // B 和 C 都至少有一位是 1,都是逻辑 1
A||B= 1 // B 是逻辑 1
B||C= 1
A||D= 0 // A 和 D 都是逻辑 0
6.4位运算符(Bitwise)
位运算是把两个操作数按对应位分别做逻辑运算:
· ~ 按位取反
· & 按位与
· | 按位或
· ^ 按位异或
· ^~ / ~^按位同或(两个符号等价)
举个例子,A=4'b1001; B=4'b1101;
~A = 4'b0110
A&B= 4'b1001
A|B= 4'b1101
A^B= 4'b0100
[注意] 两个长度不同的操作数做位运算时,会自动按右端对齐,短的高位补 0。
6.5关系运算符(Relational)
· < 小于
· <= 小于或等于
· > 大于
· >= 大于或等于
返回值规则:
· 关系为假,返回 0
· 关系为真,返回 1
· 操作数有不定值 x,结果就是 x
6.6等式运算符(Equality)
· == 等于
· != 不等于
· === 全等(不可综合)
· !== 不全等(不可综合)
和 C 语言的差别就在 === 和 !== 上。普通的 == 比较时,遇到不定态 x 或高阻 z,结果就是 x;只有 === 才要求每一位都严格相同,x 就是 x,z 就是 z,所以 === 不可综合,只用于仿真。
举个例子,D=4'b1x01, a=4'b1x01;
a == b // 结果是 x,因为有 x 参与
a === b // 结果是 1,每一位都严格相等
6.7缩位运算符(Reduction)
缩位运算和位运算不一样,是对单个操作数进行与、或、非递推,结果是 1 位。符号放在操作数前面:
· & 与
· ~& 与非
· | 或
· ~| 或非
· ^ 异或
· ^~ / ~^同或
举个例子:
reg a;
b = &a; // 等价于 b = ((a & a) & a) & a
若 A=5'b11001:
&A = 0 // 所有位都为 1 才为 1
|A = 1 // 所有位都为 0 才为 0
~|A= 0
^A = 1 // 1 的个数为奇数
6.8移位运算符(Shift)
· >> 右移
· << 左移
是逻辑移位,移出的位都用 0 填补。
举个例子,A=5'b11001;
A >> 2 = 5'b00110 // 右移 2 位,左边补 0
A << 2 = 5'b00100 // 左移 2 位,右边补 0(低 2 位被移出丢弃)
6.9条件运算符(Conditional)
这是 Verilog 里唯一的三目运算符,格式:
信号 = 条件 ? 表达式1 : 表达式2;
当条件成立时,信号取表达式 1 的值,否则取表达式 2 的值。最典型的应用就是二选一多路选择器:
// 二选一 MUX
out = sel ? in1 : in0; // sel=1 时 out=in1,否则 out=in0
6.10位拼接运算符(Concatenation)
用 { } 把两个或多个信号的某些位拼接起来:
{信号1的某些位, 信号2的某些位, ..., 信号n的某些位}
例如:
wire a, b;
wire c;
c = {a, b}; // 把 a 的高 3 位和 b 的低 3 位拼起来
位拼接还支持重复法来简化书写:
{3{a, b}} // 等价于 {{a, b}, {a, b}, {a, b}},也等价于 {a, b, a, b, a, b}
{3{1'b0}} // 结果为 6'b000000
位拼接在符号位扩展时也特别方便:
wire Data;
wire s_data;
s_data = {{4{Data}}, Data}; // 把符号位扩展到 12 位
================================================================
七、运算符优先级
================================================================
运算符种类多了之后优先级容易搞混,所以最后强烈建议一个习惯:
写程序的时候,如果不确定优先级,就直接用括号 ( ) 把它括起来!
这一点对调试代码特别有用,能省掉很多"我明明写的没问题为什么结果不对"的纠结时间。
================================================================
八、整体小结
================================================================
这一篇比较长,把 Verilog 里"数据怎么放"和"数据怎么算"两块基础合在一起过了一遍。
[向量与存储器]
· 向量:宽度大于 1 位的变量,wire 和 reg 都可以是向量
· 位选择和域选择: 选一位, 选连续几位
· 存储器:reg 型的二维阵列,用 [位宽-1:0] 名字 [容量-1:0] 声明
· 存储器只能对单个单元整体赋值,不支持位选和域选
· n 位寄存器可以整体赋值,n 个 1 位寄存器排成的存储器不行
[运算符全家福]
· 算术:+、-、*、/、%
· 逻辑:&&、||、!
· 位运算:~、&、|、^、^~
· 关系:<、<=、>、>=
· 等式:==、!=、===、!==
· 缩位:对单个操作数递推,结果 1 位
· 移位:>>、<<
· 条件:?:(唯一的三目运算符)
· 位拼接:{ },支持重复语法
顺着老哥之前的帖子一路找过来了,我是准备明年考研的,也是计算机系的,想找老哥要点推荐的资料和课程{:5_180:} 1739986716 发表于 2026-7-24 21:49
顺着老哥之前的帖子一路找过来了,我是准备明年考研的,也是计算机系的,想找老哥要点推荐的资料和课程{:5_ ...
找对了人孩子,我是去年看了楼主帖子考上研究生的,我私信你把焚决给你,明年考上了别忘了报喜 1739986716 发表于 2026-7-24 21:49
顺着老哥之前的帖子一路找过来了,我是准备明年考研的,也是计算机系的,想找老哥要点推荐的资料和课程{:5_ ...
具体啥专业啊,11408?
下一篇写个 Vivado入门指南 手搓一个risc v出来{:4_108:} cheec 发表于 2026-7-27 13:07
下一篇写个 Vivado入门指南 手搓一个risc v出来
那得拍到比较后面了,先把verilog语法讲清楚,我再想想vivado教程怎么写吧
页:
[1]