[Verilog14]HDLBits习题_Vectors

HDLBits习题讲解_Vectors

矢量

  • 矢量用于使用一个名称对相关信号进行分组,以便于操作。例如,wire[7:0] w,声明了一个具有8位的矢量,其功能相当于8个一位的wire
  • 声明矢量的具体格式如下:
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.

Vectors

  • 构建一个具有一个 3 位输入的电路,然后输出相同的矢量,并将其拆分为三个单独的 1 位输出。将输出连接到输入矢量的o0,o1,o2。代码如下:
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

Vectors in more detail

  • 构建一个组合电路,将输入的半字(16 位、[15:0] )分成较低的 [7:0] 和上 [15:8] 字节。代码如下:
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    assign out_hi[7:0] = in[15:8];
    assign out_lo[7:0] = in[7:0];
endmodule

Vector part select

  • 32 位矢量可被视为包含 4 字节(位 [31:24]、[23:16]等)。构建一个电路,进行大小端转换。例如AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa。当需要交换一段数据的大小端时,通常使用此操作,例如在小端 x86 系统和许多 Internet 协议中使用的大端格式之间。代码如下:
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];
endmodule

Bitwise operators

  • 构建一个具有两个 3 位输入的电路,计算两个向量的按位或、两个向量的逻辑或 和两个向量的按位反向(非)。将b的反向放在上半部分(即位 [5:3]),将a反向放在下半部分(即位 [2:0])。代码如下:
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

Four-input gates

  • 在[3:0]中用四个输入构建一个组合电路。有3个输出:
  1. out_and:输出4输入和门。
  2. out_or:输出4输入或门。
  3. out_xor:输出4输入XOR门。
  • 代码如下:
module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
	assign out_and = ∈
    assign out_or = |in;
    assign out_xor = ^in;
endmodule

位拼接运算符

  • 位拼接运算符{}。用这个运算符可以把两个或多个信号的某些位拼接起来进行运算操作。
  • 当在使用位拼接表达式时不允许存在没有指明位数的信号。这是因为在计算拼接信号的位宽的大小时必需知道其中每个信号的位宽。
  • {信号1的某几位,信号2的某几位,..,..,信号n的某几位}。如:
input [7:0] A, B;
input Cin;
output [7:0] Sum; // 和输出
output Cout; // 进位输出
assign {Cout, Sum} = A + B + Cin; // 进位与和拼接在一起
  • 位拼接还可以用重复法来简化表达式 {num{vector}}。举例如下:
{4{w}} //这等同于{w,w,w,w}
{b,{3{a,b}}} //这等同于{b,a,b,a,b,a,b}
//需要注意,在重复表达式中的4和3,务必为常数表达式

Vector concatenation operator

  • 给定多个输入向量,将它们聚集在一起,然后将其拆分为多个输出向量。有六个 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[7:0],x[7:0],y[7:0],z[7:0]} = { a[4:0],b[4:0],c[4:0],d[4:0],e[4:0],f[4:0],2'b11};
endmodule

Vector reversal 1

  • 如果输入矢量为 8 位 [7:0],则倒转其位并输出。
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

tips: 如果写成assign out[7:0] = in[0:7];;是无法正常运行的,这是因为在verilog语法中,是不允许直接这样将输入的向量进行翻转。

Replication operator

  • 构建一个电路,将 8 位编号扩展到 32 位。这需要将符号位复制24 个符号位复制24次,(即复制位[7] 24 次),然后是 8 位数字本身。代码如下:
module top_module (
    input [7:0] in,
    output [31:0] out );//
    assign out = {{24{in[7]}},in[7:0]};
endmodule

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;
  • 使用位拼接运算符,可以更为简单的实现该代码。代码如下:
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}});
endmodule


参考:
HDLBits
HDLBits答案(2)_Verilog向量基础