Vector0
构建一个具有一个3位输入的电路,然后输出相同的矢量,并将其分成三个独立的1位输出。将输出连接到输入向量的位置 0、位置 1 等。o0,o1在图中,旁边带有数字的刻度线表示矢量(或“总线”)的宽度,而不是为矢量中的每个位绘制单独的线。
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
![]()
仿真图片:
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 = in[15:8];
assign out_lo = in[7:0];
endmodule
仿真图片:
Vector part seledt
可以将 32 位向量视为包含 4 个字节(位 [31:24]、[23:16] 等)。构建一个电路,该电路将反转 4 字节字的字节顺序。
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
Biwise operators
构建一个具有两个 3 位输入的电路,用于计算两个向量的按位或、两个向量的逻辑或以及两个向量的逆 (NOT)。b的非给out_not[5:3],a的非给out_not[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[2:0] = ~a;
assign out_not[5:3] = ~b;
endmodule
Four-input gates
构建一个具有四个输入的组合电路in[3:0],有3个输出:
- out_and:4 输入与门的输出。
- out_or:4 输入或门的输出。
- out_xor:4 输入异或门的输出。
//solution 1
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = in[0]&in[1]&in[2]&in[3];
assign out_or = in[0]|in[1]|in[2]|in[3];
assign out_xor = in[0]^in[1]^in[2]^in[3];
endmodule
//solution 2
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈//reduction operator
assign out_or = |in;
assign out_xor = ^in;
endmodule
Vector concatenation operator
部分选择用于选择向量的部分。连接运算符{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}是非法的,并导致错误消息:unsized constants are not allowed in concatenations。
练习:给定几个输入向量,将它们连接在一起,然后将它们分成几个输出向量。有六个 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};
// assign { ... } = { ... };
endmodule
Vector reversal 1
给定一个 8 位输入向量 [7:0],反转其位顺序。
- assign out [7:0] = in[0:7]; 不起作用,因为 Verilog 不允许翻转矢量位顺序。
- 连接运算符可以节省一些编码,允许 1 个分配语句而不是 8 个。
//solution 1
module top_module (
input [7:0] in,
output [7:0] out
);
assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in;
endmodule
//solution 2
module top_module (
input [7:0] in,
output [7:0] out
);
always @(*) begin
for (int i=0; i<8; i++) // int is a SystemVerilog type. Use integer for pure Verilog.
out[i] = in[8-i-1];
end
endmodule
//solution 3
module top_module (
input [7:0] in,
output [7:0] out
);
generate
genvar i;
for (i=0; i<8; i = i+1) begin: my_block_name
assign out[i] = in[8-i-1];
end
endgenerate
endmodule
Replication operator
构建一个将 8 位数字符号扩展为 32 位的电路。这需要连接 24 个符号位副本(即复制位 [7] 24 次),然后是 8 位数字本身。
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
More replication
给定五个 1 位信号(a、b、c、d 和 e),计算 25 位输出向量中的所有 25 个成对的一位比较。如果被比较的两位相等,则输出应为 1。
如图所示,使用复制和连接运算符可以更轻松地完成此操作。
- 顶部向量是每个输入的 5 次重复的串联
- 底部向量是 5 个输入的串联的 5 次重复
module top_module (
input a, b, c, d, e,
output [24:0] out
);
wire [24:0] top, bottom;
assign top = { {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} };
assign bottom = {5{a,b,c,d,e}};
assign out = ~top ^ bottom; // Bitwise XNOR
// This could be done on one line:
// assign out = ~{ {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} } ^ {5{a,b,c,d,e}};
endmodule