【HDLbits刷题笔记 】02-verilog语法-向量部分

vectors

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

请注意,向量的声明将维度放在向量名称之前,这与 C 语法相比是不寻常的。但是,正如您所期望的那样,零件选择在矢量名称之后具有尺寸。

wire [99:0] my_vector;      // Declare a 100-element vector
assign out = my_vector[10]; // Part-select one bit out of the vector

构建一个具有一个3位输入的电路,然后输出相同的矢量,并将其分成三个独立的1位输出。将输出连接到输入向量的位置 0、位置 1 等。o0o1

在图中,旁边带有数字的刻度线表示矢量(或“总线”)的宽度,而不是为矢量中的每个位绘制单独的线。

【HDLbits刷题笔记 】02-verilog语法-向量部分_第1张图片
module top_module ( 
    input wire [2:0] vec,
    output wire [2:0] outv,
    output wire o2,
    output wire o1,
    output wire o0  ); // Module body starts after module declaration
    assign o0=vec[0];
    assign o1=vec[1];
    assign o2=vec[2];
    assign outv[2:0]=vec[2:0];//or assign outv=vec;
endmodule

vectors in more detail

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

声明向量

必须声明向量:

键入 [上:下] vector_name;

type [upper:lower] vector_name;

类型指定向量的数据类型。这通常是电线或注册。如果要声明输入或输出端口,则该类型还可以包括端口类型(例如,输入或输出)。一些例子:

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.

向量的字节序(或非正式地称为“方向”)是最低有效位是否具有较低的索引(小端序,例如 [3:0])或较高的索引(大端序,例如 [0:3])。在 Verilog 中,一旦向量声明具有特定的字节序,就必须始终以相同的方式使用它。例如,在宣布时书写是非法的。与字节序保持一致是一种很好的做法,因为如果将不同字节序的向量分配或一起使用,就会出现奇怪的错误。vec[0:3] vecwire [3:0] vec;

隐式网络(Implicit nets

隐式网络通常是难以检测的错误的来源。 在 Verilog 中,网络型(net)信号可以通过语句或通过将未声明的内容附加到模块端口来隐式创建。

在Verilog当中,如果在一个assign语句或者一个未被声明的模块当中出现/引用未声明的向量,Implicit nets 就会被隐性地生成在模块当中。Implicit nets一般都是一位wire变量,如果作为向量使用,很可能会报错。

用指令default_nettype none可以禁止Implicit nets 的生成。

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

未打包数组与打包数组(Unpacked vs. Packed Arrays

在 Verilog-2001 中,所有数据类型都可以声明为数组。reg、wire 和所有其他网络类型也可以声明矢量宽度。在对象名称之前声明的维度称为“矢量宽度”维度。在对象名称之后声明的维度称为“数组”维度。

SystemVerilog 使用术语打包数组来指代对象名称之前声明的维度(Verilog-2001 将其称为矢量宽度)。术语未打包数组用于指对象名称后声明的维度。

输出

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

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.

访问矢量元素:Part-Select

访问整个向量是使用向量名称完成的。例如:

assign w = a;

获取整个 4 位向量 A 并将其分配给整个 8 位向量 W(声明取自上面)。如果左右两侧的长度不匹配,则会根据需要将其零扩展或截断。

部分选择运算符可用于访问矢量的一部分:

一点练习

构建一个组合电路,将输入半字(16 位,[15:0])拆分为较低的 [7:0] 和高部 [15:8] 字节。

vecot part select 选择

可以将 32 位向量视为包含 4 个字节(位 [31:24]、[23:16] 等)。构建一个电路,该电路将反转 4 字节字的字节顺序。

AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa

当一段数据的字节序需要交换时,例如在小端x86系统和许多Internet协议中使用的大端格式之间,通常使用此操作。

module top_module(

bitwise operation按位运算

构建一个具有两个 3 位输入的电路,用于计算两个向量的按位 OR、两个向量的逻辑 OR 以及两个向量的逆 (NOT)。将 的反半部分(即位 [5:3]),将 的反半部分放在下半部分。bout_nota

按位运算符与逻辑运算符

前面,我们提到各种布尔运算符有按位和逻辑版本.使用向量时,两种运算符类型之间的区别变得很重要。两个 N 位向量之间的按位运算复制向量每个位的操作并生成 N 位输出,而逻辑运算将整个向量视为布尔值(true = 非零,false = 零)并生成 1 位输出。

查看模拟波形,了解按位 OR 和逻辑 OR 有何不同

【HDLbits刷题笔记 】02-verilog语法-向量部分_第2张图片

four-input gates

构建一个具有四个输入的组合电路,in[3:0]。

有 3 个输出:

  • out_and:4输入AND门的输出。

  • out_or:4输入OR门的输出。

  • out_xor:4输入异或门的输出。

vector concatenation operation 位拼接运算

Part selection选择用于选择矢量的部分。串联运算符 {a,b,c} 用于通过将矢量的较小部分连接在一起来创建更大的向量。

串联需要知道每个组件的宽度(或者你怎么知道结果的长度?因此,{1, 2, 3} 是非法的,并导致错误消息:串联中不允许使用未调整大小的常量。

串联运算符可用于赋值的左侧和右侧。

一点练习

给定几个输入向量,将它们连接在一起,然后将它们分成几个输出向量。有六个 5 位输入向量:a、b、c、d、e 和 f,总共 30 位输入。有四个 8 位输出向量:w、x、y 和 z,用于 32 位输出。输出应该是输入向量的串联,后跟两个 1 位:

【HDLbits刷题笔记 】02-verilog语法-向量部分_第3张图片

vector reversal 1

给定一个 8 位输入向量 [7:0],反转其位顺序。

replication operation复制运算

串联运算符允许将向量连接在一起以形成更大的向量。但是有时您希望将同一件事连接在一起很多次,并且执行诸如分配 a = {b,b,b,b,b,b}; 之类的事情仍然很乏味。复制运算符允许重复一个向量并将它们连接在一起:

{num{vector}}

这将按数字次复制矢量num 必须是一个常量。两组括号都是必需的。

例子:

{5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f)

{2{a,b,c}} // The same as {a,b,c,a,b,c}

{3'd5, {2{3'd6}}} // 9'b101_110_110. It's a concatenation of 101 with

// the second vector, which is two copies of 3'b110.

一点练习

查看复制运算符的一个常见位置是将较小的数字符号扩展到较大的数字,同时保留其值。这是通过将较小数字的符号位(最高有效位)复制到左侧来完成的。例如,将 4'b0 101 (5) 符号扩展为 8 位会产生 8'b 0000 0101 (5),而将 4'b 1 101 (-3) 符号扩展为 8 位会产生 8'b 1111 1101 (-3)。

构建一个将 8 位数字符号扩展到 32 位的电路。这需要连接符号位的 24 个副本(即复制位 [7] 24 次),后跟 8 位数字本身。

more replication

给定五个 1 位信号(a、b、c、d 和 e),计算 25 位输出向量中的所有 25 个成对一比特比较。如果要比较的两个位相等,则输出应为 1。

out[24] = ~a ^ a; // a == a, so out[24] is always 1.

out[23] = ~a ^ b;

out[22] = ~a ^ c;

...

out[ 1] = ~e ^ d;

out[ 0] = ~e ^ e;

【HDLbits刷题笔记 】02-verilog语法-向量部分_第4张图片

如图所示,使用复制和串联运算符可以更轻松地完成此操作。

  • 顶部向量是每个输入的 5 个重复的串联

  • 底部向量是 5 个输入串联的 5 个重复

2.3 Verilog 数据类型 | 菜鸟教程 (runoob.com)

你可能感兴趣的:(HDLbits学习,fpga开发)