HDLBits答案(2)_Verilog向量基础知识
HDLBits_Verilog向量基础知识
向量
在Verilog中,对向量维度的声明在向量名之前,这点与C语言有所差异,但使用向量的时候维度信息仍在向量名后。
1 | wire [99:0] my_vector; // Declare a 100-element vector |
向量的更多知识
声明向量
type [upper:lower] vector_name;
type
指定了向量的数据类型,通常为reg或wire类型。如果声明的是输入、输出向量的话,类型前还可以加上input和output,如下所示:
1 | wire [7:0] w; // 8-bit wire |
向量的大小端是指最不重要的位具有较低的索引([3:0])还是较高的索引([0:3]),一旦用特定的索引规则定义了向量,就要用相同的方式去使用它。
tips:向量声明时数字的顺序很重要,它决定了向量是以大端存储或者小端存储。举例说明,若声明wire [3:0] w
,则w[0]
为w的最低位,w[3]
为w的最高位;若声明为wire [0:3] w
,则与上述结果相反。所以在向量的定义和使用时一定要保持大小端一致!
未定义的中间变量容易出错
使用wire型变量前请先声明,不要图一时之便直接未定义就拿来做中间变量,这样导致的错误会很难发现。
1 | wire [2:0] a, c; // Two vectors |
向量名前为维度,向量名后为数目,不写统统视作1。(可类比C语言中的数组,向量名前为数组元素的数据类型,向量名后为数组长度;或者形象化的表述为:维度即为每个房子的大小,数目为房子的总数目)
1 | reg [7:0] mem [255:0]; // 256 unpacked elements, each of which is a 8-bit packed vector of reg. |
获取向量元素:部分选择
访问整个向量是使用向量名完成的,如:assign w = a;
如果左右两边的长度不匹配,则根据情况对向量进行补零或截断。
向量的部分选择操作可以访问向量的一部分。(向量声明来自上面”声明向量”部分)
1 | w[3:0] // Only the lower 4 bits of w |
tips:取用向量中特定维度的数时一定注意要与向量的定义一致,注意大小端匹配的问题。
题目描述:
构建一个电路将一个4byte的数中的字节顺序调转,常用于数据的大小端转换。
AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa
Solution:
1 | module top_module( |
tips:在向量赋值的左右两端都可以选择对部分数据进行操作。
对向量进行门操作
位操作运算符VS逻辑操作运算符
对两个Nbit位宽的向量而言,按位操作输出为Nbit位宽向量;而逻辑操作将整个向量视为布尔值(true =非零,false =零)并产生一个1bit的输出。
题目描述1:对向量特定部分的数据进行按位操作和逻辑操作。
Solution1:
1 | module top_module( |
题目描述2:
对输入向量进行按位的与、或和异或操作。
Solution2:
1 | module top_module( |
tips:合理利用缩位运算符精简代码,按位进行逻辑运算,结果为1bit数。
- 与缩位运算符:&
- 或缩位运算符:|
- 异或缩位运算符:^
- 与、或、异或运算符和非运算符组成的复合运算符:&,|, ~,^
向量拼接操作
向量拼接操作需要知道待拼接的各向量的位宽,否则你怎么知道结果的位宽?所以{1,2,3}是无效的,因为你未指定向量位宽。
向量的拼接操作在赋值的左右两端均可使用。
1 | input [15:0] in; |
tips:1、位宽合并需知道各成分的确切位宽,否则结果位宽不定。2、位宽合并时在assign两端均可实现,最好左右两端位宽相同,否则未被指定的数据会被置零。
题目描述:
给定几个输入向量,将它们拼接在一起,然后将它们分割成几个输出向量。有6个5位输入向量:a, b, c, d, e, f,总共30位输入。对于32位的输出,有4个8位的输出向量:w、x、y和z。输出应该是输入向量与两个“1”位的串联:
Solution:
1 | module top_module ( |
向量翻转
题目描述:
给定一个8位输入向量[7:0],颠倒它的位顺序。
Solution1:
1 | module top_module( |
Solution2:
1 | module top_module( |
tips:建议使用Solution2实现,可扩展性强。
向量复制操作
向量复制操作允许重复一个向量并将它们连接在一起:{num{vector}}
例如:
1 | {5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f) |
tips:复制向量有捷径,花括外面带数字。主要用于符号位的拓展。如4’b0101带符号拓展为8bit的话为8’b00000101,4’b1101带符号拓展为8bit数为8’b11111101。
题目描述:建立一个电路,将8位数字扩展到32位。这需要将符号位的24个副本(即将位[7]复制24次)与8位数字本身连接起来。
Solution:
1 | module top_module ( |
题目描述2:给定5个1位信号(a、b、c、d和e),计算25位输出向量中所有25个成对的1位比较。如果两个被比较的位相等,输出应该是1。
1 | out[24] = ~a ^ a; // a == a, so out[24] is always 1. |
tips:该操作可以定位特定signal所在位置,两向量重复数据有规律可循,可用复制的方式来产生,简化代码。
Solution:
1 | module top_module ( |
总结:
学习了向量操作的相关知识,包括声明、选择部分数据、合并、复制等操作。