掌握 Verilog 拼接操作:实用指南
多位 Verilog 线网和变量可通过 拼接 运算符 { 和 } 用逗号分隔组合成更宽的多线网线网或变量。拼接操作数除线网和变量外,还允许表达式和带位宽常数。
必须知道每个操作数尺寸以计算完整拼接尺寸。
Verilog 拼接示例
wire a, b; // 1-bit wire
wire [1:0] res; // 2-bit wire to store a and b
// res[1] follows a, and res[0] follows b
assign res = {a, b};
wire [2:0] c;
wire [7:0] res1;
// res[0] follows c[2]
// res[2:1] is always 0
// res[4:3] follows c[1:0]
// res[5] follows a
// res[6] follows b
assign res1 = {b, a, c[1:0], 2'b00, c[2]};
下面是拼接输入形成不同输出的工作设计示例。拼接表达式可直接显示或赋给任意线网或变量,不一定是输出。
module des (input [1:0] a, input [2:0] b, output [4:0] out1, output [3:0] out2 );
assign out1 = {a, b};
assign out2 = {a[1], 2'b01, b[2]};
endmodule
module tb;
reg [1:0] a;
reg [2:0] b;
wire [4:0] out1;
wire [3:0] out2;
des u0 (a, b, out1, out2);
initial begin
a <= 0; b <= 0;
$monitor("[%0t] a=%b b=%b, out1=%b out2=%b", $time, a, b, out1, out2);
#10 a <= 3;
#5 b <= 5;
#10 a <= 2;
#5 b <= 1;
#10 $finish;
end
endmodule
注意 out2[2:1] 始终为常量 2'b01。
仿真日志
xcelium> run [0] a=00 b=000, out1=00000 out2=0010 [10] a=11 b=000, out1=11000 out2=1010 [15] a=11 b=101, out1=11101 out2=1011 [25] a=10 b=101, out1=10101 out2=1011 [30] a=10 b=001, out1=10001 out2=1010 Simulation complete via $finish(1) at time 40 NS + 0
复制运算符
当同一表达式需重复多次时,使用复制常数,必须为非负数,不能是 X、Z 或变量。该常数也包含在大括号内,与原拼接运算符一起,指示表达式重复总次数。
wire a;
wire [6:0] res;
assign res = {7{a}};
{2'bz{2'b0}} // 非法:复制常数不能为 Z
{2'bx{2'b0}} // 非法:复制常数不能为 X
复制表达式不能出现在赋值左侧,不能连接到 output 或 inout 端口。
module des;
reg [1:0] a;
reg [2:0] b;
initial begin
a <= 2; b <= 4;
#10;
$display("a=%b b=%b res=%b", a, b, {{2{a}}, {3{b}}});
end
endmodule
注意 a 重复两次,b 重复三次。
仿真日志
xcelium> run a=10 b=100 res=1010100100100 xmsim: *W,RNQUIE: Simulation is complete.
操作数在复制表达式执行时仅求值一次,即使常数为零。
嵌套复制
复制表达式允许用在常规拼接表达式内。以上例为基础,将 a 和 b 包含进总拼接表达式。
module des;
reg [1:0] a;
reg [2:0] b;
initial begin
a <= 2; b <= 4;
#10;
$display("a=%b b=%b res=%b", a, b, {a, b, 3'b000, {{2{a}}, {3{b}}}});
end
endmodule
仿真日志
xcelium> run a=10 b=100 res=101000001010100100100 xmsim: *W,RNQUIE: Simulation is complete.
非法用法
module des;
reg [1:0] a;
reg [2:0] b;
reg [3:0] _var;
initial begin
a <= 2; b <= 4; _var <= 3;
// 非法:变量不能用作复制常数
$display("a=%b b=%b res=%b", a, b, {_var{a}});
end
endmodule
编译错误如下:
Top level design units: des
$display("a=%b b=%b res=%b", a, b, {_var{a}});
| xmelab: *E,NOTPAR (./testbench.sv,12|45): Illegal operand for constant expression [4(IEEE)].
Verilog
- Verilog基础:设计你的第一个与门
- Verilog 入门:数字电路设计完整教程
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例