HDLBits——Vectors

本人持续更新HDLBits其他题目,详细讲解我们使用Verilog编程时会遇到的各种错误,若有兴趣可以移步我的博客中心浏览本人的其他文章,感谢赏光!

Vectors are used to group related signals using one name to make it more convenient to manipulate. For example, wire [7:0] w; declares an 8-bit vector named w that is equivalent to having 8 separate wires.

Contents
1 Declaring Vectors
1.1 Implicit nets
1.2 Unpacked vs. Packed Arrays
2 Accessing Vector Elements: Part-Select
3 A Bit of Practice
Declaring Vectors
Vectors must be declared:

type [upper:lower] vector_name;

type specifies the datatype of the vector. This is usually wire or reg. If you are declaring a input or output port, the type can additionally include the port type (e.g., input or output) as well. Some examples:

wire [7:0] w; // 8-bit wire
reg [4:1] x; // 4-bit reg
output reg [0:0] y; // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z; // 6-bit wire input (negative ranges are allowed)
output [3:0] a; // 4-bit output wire. Type is ‘wire’ unless specified otherwise.
wire [0:7] b; // 8-bit wire where b[0] is the most-significant bit.
The endianness (or, informally, “direction”) of a vector is whether the the least significant bit has a lower index (little-endian, e.g., [3:0]) or a higher index (big-endian, e.g., [0:3]). In Verilog, once a vector is declared with a particular endianness, it must always be used the same way. e.g., writing vec[0:3] when vec is declared wire [3:0] vec; is illegal. Being consistent with endianness is good practice, as weird bugs occur if vectors of different endianness are assigned or used together.

Implicit nets
Implicit nets are often a source of hard-to-detect bugs. In Verilog, net-type signals can be implicitly created by an assign statement or by attaching something undeclared to a module port. Implicit nets are always one-bit wires and causes bugs if you had intended to use a vector. Disabling creation of implicit nets can be done using the `default_nettype none directive.

wire [2:0] a, c; // Two vectors
assign a = 3’b101; // a = 101
assign b = a; // b = 1 implicitly-created wire
assign c = b; // c = 001 <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
// This could be a bug if the port was intended to be a vector.

Adding `default_nettype none would make the second line of code an error, which makes the bug more visible.

Unpacked vs. Packed Arrays
You may have noticed that in declarations, the vector indices are written before the vector name. This declares the “packed” dimensions of the array, where the bits are “packed” together into a blob (this is relevant in a simulator, but not in hardware). The unpacked dimensions are declared after the name. They are generally used to declare memory arrays. Since ECE253 didn’t cover memory arrays, we have not used packed arrays in this course. See http://www.asic-world.com/systemverilog/data_types10.html for more details.

reg [7:0] mem [255:0]; // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
reg mem2 [28:0]; // 29 unpacked elements, each of which is a 1-bit reg.
Accessing Vector Elements: Part-Select
Accessing an entire vector is done using the vector name. For example:

assign w = a;
takes the entire 4-bit vector a and assigns it to the entire 8-bit vector w (declarations are taken from above). If the lengths of the right and left sides don’t match, it is zero-extended or truncated as appropriate.
The part-select operator can be used to access a portion of a vector:

w[3:0] // Only the lower 4 bits of w
x[1] // The lowest bit of x
x[1:1] // …also the lowest bit of x
z[-1:-2] // Two lowest bits of z
b[3:0] // Illegal. Vector part-select must match the direction of the declaration.
b[0:3] // The upper 4 bits of b.
assign w[3:0] = b[0:3]; // Assign upper 4 bits of b to lower 4 bits of w. w[3]=b[0], w[2]=b[1], etc.
A Bit of Practice
Build a combinational circuit that splits an input half-word (16 bits, [15:0] ) into lower [7:0] and upper [15:8] bytes.

1、标准正确解答

module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    assign out_hi = in[15:8];
    assign out_lo = in[7:0];
endmodule

2、伪正确解答

module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    assign out_hi = in[15:8];
    assign out_lo = in[8:0];
endmodule

这两个解答都可以解决这道题目,但是细心的朋友就会发现在对out_lo赋值的过程,标准正确解答是assign out_lo = in[7:0];而伪正确解答是assign out_lo = in[8:0]; 之所以都能Sucess 是因为out_lo本来就是一个8bit bus wires ,即使给一个9bit的输入给它 ,out_lo也只会接收其低8位。

这既是一个错误,也是启示.
1、我们可以反过来用,比如一个9位实时输入激励信号—[8:0]in, 输出[7:0]out是一个8位的信号,要求该八位信号是该9位信号的二分频,此时我们就可以 assign out = [8:0]in; 从而实现二分频。
2、应用在某些ADC中。

以下是上述题目的中文翻译

向量用于使用一个名称对相关信号进行分组,以使其更易于操作。例如,电线[7:0] w; 声明一个名为w的8位向量,该向量等效于具有8条独立的导线。

内容
1 声明向量
1.1 隐式网
1.2未 包装与已包装阵列
2 访问向量元素:部分选择
3 点练习
声明向量
向量必须声明:

输入[upper:lower] vector_name;

type指定向量的数据类型。这通常是wire或reg。如果要声明输入或输出端口,则该类型还可以另外包括端口类型(例如,input或output)。一些例子:

电线[7:0] w; // 8位线
reg [4:1] x; // 4位reg
输出reg [0:0] y; // 1位reg也是一个输出端口(这仍然是一个向量)
输入线[3:-2] z; // 6位线输入(允许负范围)
输出[3:0] a; // 4位输出线。除非另有说明,否则类型为“电线”。
线[0:7] b; // 8位连线,其中b [0]是最高有效位。
向量的字节序(或非正式地称为“方向”)是指最低有效位是具有较低的索引(较小的字节序,例如[3:0])还是具有较高的索引(较大的字节序,例如[[ 0:3])。在Verilog中,一旦以特定的字节序声明了向量,就必须始终以相同的方式使用它。例如,声明vec[0:3]时写是非法的。与字节序一致是一种好习惯,因为如果将不同字节序的向量一起分配或使用,则会发生奇怪的错误。 vecwire [3:0] vec;

隐网
隐式网络通常是难以发现的错误的来源。在Verilog中,可以通过assign语句或通过将未声明的内容附加到模块端口来隐式创建网络类型信号。隐式网络始终是一位导线,如果您打算使用矢量,则会导致错误。可以使用`default_nettype none指令来禁止创建隐式网络。

wire [2:0] a, c; // Two vectors
assign a = 3’b101; // a = 101
assign b = a; // b = 1 implicitly-created wire
assign c = b; // c = 001 <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
// This could be a bug if the port was intended to be a vector.

添加`default_nettype none将使第二行代码出错,从而使该错误更明显。

未包装阵列与已包装阵列
您可能已经注意到,在声明中,矢量索引写在矢量名称之前。这声明了数组的“打包”维,其中位被“打包”到了一个Blob中(这在模拟器中是相关的,但在硬件中不相关)。将解压后的尺寸宣布后的名称。它们通常用于声明内存数组。由于ECE253没有涵盖内存阵列,因此在本课程中我们没有使用压缩数组。有关更多详细信息,请参见http://www.asic-world.com/systemverilog/data_types10.html。

reg [7:0] mem [255:0]; // 256个未压缩的元素,每个元素都是reg的8位压缩向量。
reg mem2 [28:0]; // 29个解压缩的元素,每个元素都是一个1位的reg。
访问向量元素:部分选择
使用向量名称可以访问整个向量。例如:

分配w = a;
取整个4位向量a并将其分配给整个8位向量w(从上面获取声明)。如果左右边的长度不匹配,则将其适当地零扩展或截断。
部分选择运算符可用于访问向量的一部分:

w [3:0] //仅w的低4位
x [1] // x的最低位
x [1:1] // //也是x的最低位
z [-1:-2] // z的两个最低位
b [3:0] //非法。矢量零件选择必须与声明的方向匹配。
b [0:3] // b的* upper * 4位。
分配w [3:0] = b [0:3]; //将b的高4位分配给w的低4位。w [3] = b [0],w [2] = b [1]等

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值