【HDLbits】01Verilog Language__2.Vectors

2.Vectors

2.1 Vectors

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

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

wire [99:0] my_vector;      // 声明一个包含100个元素的向量
assign out = my_vector[10]; // 部分选择向量中的一位

构建一个电路,它有一个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 o0=vec[0];
    assign o1=vec[1];
    assign o2=vec[2];
    assign outv=vec[2:0]; //assign outv=vec;
endmodule

2.2 Vectors in more detail

向量必须声明: type [upper:lower] vector_name;

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

`default_nettype none     // 禁用隐式网络,减少某些类型的bug。
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];   //连接操作符也可以:assign {out_hi, out_lo} = in;
endmodule

2.3 Vectors part select(矢量零件选择)

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

module top_module( 
    input [31:0] in,
    output [31:0] out );
    assign  out[31:24] = in[7:0];
    assign  out[23:16] = in[15:8];
    assign  out[15:8] = in[23:16];
    assign  out[7:0] = in[31:24];
    // assign out[31:24] = ...;
endmodule

2.4 Bitwise / Logical Operators(按位/逻辑运算符)

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

构建一个有两个3位输入的电路,用于计算两个向量的位或,两个向量的逻辑或,以及两个向量的逆(NOT)。将b的倒数放在out_not的上半部分(即bits[5:3]),并将a的倒数放在下半部分。
查看模拟波形,了解按位 OR 和逻辑 OR 有何不同。
在这里插入图片描述

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};  //或 out_not = {~b,~a}

endmodule

2.5 Four-input gates(四输入门)

构建一个具有四个输入的组合电路,in[3:0]。有 3 个输出:
out_and:4输入AND门的输出。
out_or:4输入OR门的输出。
out_xor:4输入异或门的输出。

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

2.6 Vector concatenation operation (向量级联运算符)

部分选择用于选择矢量的部分。连接操作符{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;  //交换两个字节。右边和左边都是16位向量。
assign out[15:0] = {in[7:0], in[15:8]};  //这是一样的。
assign out = {in[7:0], in[15:8]};  //这是不同的。右边的16位向量被扩展以匹配左边的24位向量,因此输出 
                                   //[23:16]为零。在前两个例子中,out[23:16]没有被赋值。

给定几个输入向量,将它们连接在一起,然后将它们分割成几个输出向量。有6个5位输入向量:a、b、c、d、e和f,总共有30位输入。有4个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

2.7 Vector reversal 1 (向量反转1)

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

assign out[7:0]= in[0:7];不能工作,因为Verilog不允许翻转向量位排序。
连接操作符可以节省一些代码,允许使用1条而不是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]};
    // assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in;
endmodule

2.8 Replication operation (复制运算符)

连接操作符允许将向量连接在一起以形成一个更大的向量。但有时你想要多次将相同的东西连接在一起,执行赋值a = {b,b,b,b};之类的操作仍然很乏味。复制操作符允许重复一个向量并将它们连接在一起:
{ num { vector } }
这个函数将vector复制num次。Num必须是常数。两组花括号都是必需的。

Examples:
{ 5 { 1’b1 } } // 5’b11111 (or 5’d31 or 5’h1f)
{ 2 { a,b,c } } // 和 {a,b,c,a,b,c}一样
{ 3’d5, { 2 { 3’d6 } } } // 9’b101_110_110. 它是101和第二个向量的串联,第二个向量是3’b110的两个副本。

复制操作符的一个常见情况是将一个较小的数字进行符号扩展为一个较大的数字,同时保留其有符号值。这是通过复制左边较小数字的符号位(最有效的位)来实现的。例如,将4’b0 101(5)扩展到8位将得到
8’b 0000 0101(5),而将4’b1 101(-3)扩展到8位将得到8’b 1111 1101(-3)。

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

module top_module (
	input [7:0] in,
	output [31:0] out
);
	assign out = { {24{in[7]}}, in };  //assign out = {复制符号位,输入}
endmodule

2.9 More replication (更多复制)

给定5个1位信号(a, b, c, d和e),在25位输出向量中计算所有25个成对的1位比较。如果被比较的两个比特相等,则输出应为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;
在这里插入图片描述

如图所示,使用复制和连接操作符可以更容易地实现这一点。

  • 顶部向量是每个输入的5个重复的串联
  • 底部向量是5个输入序列的5次重复
  • 输出是通过连接和复制五个输入,创建的两个向量的XNOR。assign out = ~{ … } ^ { … };
module top_module (
    input a, b, c, d, e,
    output [24:0] out );
    
    wire [24:0]m = { {5{a}},{5{b}},{5{c}},{5{d}},{5{e}} };
    wire [24:0]n = {5{a,b,c,d,e}};
    assign out = ~m^n;
    // 或直接 assign out = ~ { {5{a}},{5{b}},{5{c}},{5{d}},{5{e}} } ^ {5{a,b,c,d,e}};
endmodule

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值