HDLBits练习汇总-02-Verilog语言--向量部分

Vector0

向量用于使用一个名称对相关信号进行分组,以使其更易于操作。例如,电线[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位输出。将输出连接o0到输入向量的位置0,o1位置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 outv=vec;
    assign o2=vec[2];
    assign o1=vec[1];
    assign o0=vec[0];
endmodule

Vector1

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

声明向量

向量必须声明:

输入      [upper:lower] vector_name;

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

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]时写是非法的。与字节序一致是一种好习惯,因为如果将不同字节序的向量一起分配或使用,则会发生奇怪的错误。

隐网

隐式网络通常是难以发现的错误的来源。在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中(这在模拟器中相关,但在硬件中不相关)。将解压后的尺寸宣布后的名称。它们通常用于声明内存数组。

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.

访问向量元素:部分选择

使用向量名称可以访问整个向量。例如:

assign w = a;

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

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

建立一个组合电路,将输入半字(16位,[15:0])分成低[7:0]和高[15:8]个字节。

Module Declaration
`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
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

Vector2(部分选择)

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

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

`default_nettype none
module top_module( 
    input [31:0] in,
    output [31:0] out );//

    assign out = {in[7:0], in[15:8], in[23:16], in[31:24]};

endmodule

按位运算符

构建一个具有两个3位输入的电路,该输入可计算两个向量的按位或,两个向量的逻辑或以及两个向量的反(NOT)。将的反数b放在out_not(的[5:3]位)的上半部分,并将其的倒数a放在下半部分。

按位与逻辑运算符

之前,我们提到了各种布尔运算符的按位和逻辑版本(例如norgate)。使用向量时,两种运算符类型之间的区别变得很重要。两个N位向量之间的按位运算会复制该向量的每个位的运算并产生N位输出,而逻辑运算会将整个向量视为布尔值(真=非零,假=零),并且产生1位输出。
查看仿真波形,了解按位或与逻辑或的不同之处。
在这里插入图片描述

module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);
    assign out_or_bitwise = a|b;
    assign out_or_logical = a||b;
    assign out_not = {~(b),~(a)};
endmodule

tips

verilog中,“!”表示逻辑求反,“~”表示按位求反。当对位宽为1的变量进行操作时,这两个操作符的作用是一样的,都是求反。当对位宽为2的变量value[1:0]进行操作时,这两个操作符的作用就不一样了.

Gates4

构建一个具有四个输入in [3:0]的组合电路。
有3个输出:
out_and:4输入与门的输出。
out_or:4输入或门的输出。
out_xor:4输入XOR门的输出。
要查看AND,OR和XOR运算符,请参见and gate,nor gate和xnor gate。

module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
    assign  out_and = & in;
	assign  out_or = | in;
    assign  out_xor= ^ in;
endmodule

Vector3(部分选择)

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

{3'b111,3'b000} => 6'b111000
{1'b1,1'b0,3'b101} => 5'b10101
{4'ha,4'd10} => 8'b10101010 // 4'ha和4'd10均为二进制的4'b1010

串联需要知道每个分量的宽度(或者您怎么知道结果的长度?)。因此,{1、2、3}是非法的,并导致出现错误消息:串联中不允许使用不定尺寸的常量。

可以在分配的左侧和右侧使用串联运算符。

input [15:0] in;
output [23:0] out;
assign {out[7:0], out[15:8]} = in;         // Swap two bytes. Right side and left side are both 16-bit vectors.
assign out[15:0] = {in[7:0], in[15:8]};    // This is the same thing.
assign out = {in[7:0], in[15:8]};       // This is different. The 16-bit vector on the right is extended to
                                        // match the 24-bit vector on the left, so out[23:16] are zero.
                                        // In the first two examples, out[23:16] are not assigned.

A Bit of Practice

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

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//

    assign {w,x,y,z} = { a, b, c, d, e, f,2'b11};

endmodule

矢量反转

给定8位输入向量[7:0],请反转其位顺序。
tips:
分配out [7:0] = in [0:7]; 由于Verilog不允许翻转向量位顺序,因此无法正常工作。
串联运算符可以节省一些编码,允许使用1个assign语句而不是8个。

module top_module( 
    input [7:0] in,
    output [7:0] out
);
    assign out = {in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7]};
endmodule

复制运算符

所述并置(或者复制)运算符允许矢量串联起来以形成更大的载体。但是有时候您想将同一事物连接在一起很多次,而做类似分配a = {b,b,b,b,b,b,b}的事情仍然很乏味;。复制运算符允许重复一个向量并将它们串联在一起:

{num {vector}}

这种复制载体由NUM倍。num必须为常数。两组嵌套都是必需的。
Examples:

{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’B 0 101(5),以8位结果在8’b 0000 0101(5),而符号扩展4’B 1 101在(-3)至8位结果8’b 1111 1101(-3)。

建立一个将8位数字符号扩展为32位的电路。这需要串联24个符号位的副本(即,复制bit [7] 24次),然后是8位数字本身。

module top_module (
    input [7:0] in,
    output [31:0] out );//
    assign out = { {24{in[7]}} ,in };

endmodule

复制操作

给定五个1位信号(a,b,c,d和e),在25位输出向量中计算所有25个成对的一位比较。如果要比较的两位相等,则输出应为1。
在这里插入图片描述
如图所示,使用复制和串联运算符可以更轻松地完成此操作。

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

module top_module (
    input a, b, c, d, e,
    output [24:0] out );//

    // The output is XNOR of two vectors created by 
    // concatenating and replicating the five inputs.
    assign out = ~{{5{a}} ,{5{b}} ,{5{c}} ,{5{d}} ,{5{e}}} ^ { {5{a,b,c,d,e}} };

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vuko-wxh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值