HDLbits——Vector

Vector

1 Vector0

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

wire [7:0] w ; 声明了一个 8 bit 位宽的信号,向量名为 w,等价于 8 个 1bit 位宽的 wire 信号。

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 o0=vec[0];
    assign o1=vec[1];
    assign o2=vec[2];
endmodule

2 Vector1

声明Vector:

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.

这里你需要了解一个向量的比特顺序(endianness)信息,比特顺序取决于向量的 LSB 是向量的高位还是地位。比如声明为 [3:0] w 的向量,LSB 是 w[0],如果声明为 [0:3] w,那么 w[3] 是 LSB 。LSB 指的是二进制数中权值最低的一位。在 Verilog 语法中,你可以将向量声明为 [3:0], 这种语法最为常见,但也可以将向量声明为 [0:3] 。这都是可以的,但必须在声明和使用时保持一致。如果声明为 wire [3:0] w ,但使用 w[0:3]赋值,这是不允许的。保持前后如一的比特顺序是很重要的一点,一些你挠破头都定位不了的 BUG 可能就是字节顺序不一致导致的。

变量隐式声明的危害

wire [2:0] a, c;    // Two vectors 
assign a = 3'b101;  // a = 101 
assign b = a;       // b =   1  隐式声明并定于了 b
wire assign c = b;  // c = 001  <-- bug 来了 b 被 coder 默认为和 a 相同的 3'b101,但其实 b 只有 1bit宽
my_module i1 (d,e); // d e 都被隐式声明为 1bit wire
                    //如果模块期望的是 vector 那么 BUG 就产生了

隐式声明的错误很容易在连接 IP 核的时候产生,从 IP 核模板文件复制来 IP 核模块后。往往会忘记声明连接 IP 模块之间的中间变量,而这些变量的隐式声明就可能被综合器“好心办了坏事”。

通过添加 ``default_nettype none` 宏定义会关闭隐式声明功能,那么这样一来,使用未声明的变量就会变成一个 Error 而不再只是 Warning。

verilog中向量与数组是两个不同的概念。 reg [7:0] count表示一个位宽为8位的向量;reg count [7:0] 表示一个一维数组,数组中的元素是位宽为1的变量;reg [7:0] count [3:0] 表示一个有4的元素的一维数组,数组中的元素是位宽为8的变量。在赋值时,我们可以直接对整个向量赋值,也可以只对向量中的某些位赋值,但是不能直接对整个数组赋值,只能对数组的某个变量或者数组的某个变量的某些位赋值。直接对数组赋值,或者将数组的值赋给其他变量,都会产生错误。

在 assign 赋值操作中,如果等号左右两侧信号的位宽不同,那么就会进行截断或者补零操作。

左侧信号位宽大于右侧信号位宽,右值的低位赋予左值对应的低位,左值高位的部分赋零

左侧信号位宽小于右侧信号位宽,右值的低位赋予左值对应的低位,右值高位的部分直接被截断。即保留右值的低位。

使用 [] 可以对信号进行片选,选择信号中特定几位比特,以下是一些片选的例子。

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]    // Z 最低两位
b[3:0]      // 如果 b 在声明时 声明为 wire [0:3] b;则不能使用 b [3:0]进行选择
b[0:3]      // b的高四位.
assign w[3:0] = b[0:3];    // 将 b 的高位赋予 w 的低位 w[3]=b[0], w[2]=b[1], etc.

输出16位输入信号的高8位和低8位

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

3 Vector2

一个 32 位的向量可以看做由 4 个字节组成(bits[31:24],[23:16],等等)。构建一个电路,将输入向量的字节顺序颠倒,也就是字节序大小端转换。

aaaaaaaabbbbbbbbccccccccdddddddd => ddddddddccccccccbbbbbbbbaaaaaaaa

这项操作常见于不同的大小端体系之间的数据交换,比如 x86 体系使用小端模式存储数据,而因特网协议中均使用大端模式,数据在本地和网络进行数据交换之前,均要进行大小端转换。

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={in[7-:8],in[15-:8],in[23-:8],in[31-:8]};两者等价
endmodule

4 Vectorgates

模块有两个 3bit 宽的输入变量 a,b ,要求输出 a,b 逐位或的,a,b 逻辑或以及 a,b 按位取反的结果,其中 b 在高位。

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_logical=a||b;//逻辑或
    assign out_or_bitwise=a|b;//按位或
    //assign out_not={~b[2],~b[1],~b[0],~a[2],~a[1],~a[0]};//等价
    assign out_not[5:3]=~b;
    assign out_not[2:0]=~a;

endmodule

5 Gates4

分别构建一个 4 输入与门,或门以及异或门。

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

endmodule

6 Vector3

连接操作符是一个很常用的运算符。

{3'b111, 3'b000} => 6'b111000
{1'b1, 1'b0, 3'b101} => 5'b10101
{4'ha, 4'd10} => 8'b10101010     // 4'ha and 4'd10 are both 4'b1010 in binary

连接运算符中的向量务必需要标注位宽,不然综合器怎么能知道你的结果需要多宽的位宽。因此 { 1,2,3 } 这样的操作是非法的,并会产生一个 Error:unsized constants are not allowed in concatenations.

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//
    assign w={a,b[4:2]};
    assign x={b[1:0],c,d[4]};
    assign y={d[3:0],e[4:1]};
    assign z={e[0],f,2'b11};
    // assign { ... } = { ... };
endmodule

7 Vectorr

Given an 8-bit input vector [7:0], reverse its bit ordering.

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

8 Vector4

在有符号数的扩展。有符号数的扩展是将符号位填充待扩展的比特。比如要将 4bit 的 4’b0101 有符号数扩展为 8bit ,0 是符号位,那么扩展之后为 8’b0000 0101.

现在要求你构建一个电路,将一个 8bit 有符号数扩展为 32bit 数。

module top_module (
    input [7:0] in,
    output [31:0] out );//
    assign out={{24{in[7]}},in};
    // assign out = { replicate-sign-bit , the-input };
endmodule

9 Vector5

module top_module (
    input a, b, c, d, e,
    output [24:0] out );//
    assign out= ~({{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}}^ {5{a,b,c,d,e}});
    // The output is XNOR of two vectors created by 
    // concatenating and replicating the five inputs.
    // assign out = ~{ ... } ^ { ... };
endmodule

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NDLilaco

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

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

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

打赏作者

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

抵扣说明:

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

余额充值