使用 Verilog assign 语句设计组合逻辑
Verilog assign 语句通常用于持续驱动 wire 数据类型信号,综合为组合逻辑。以下是更多使用 assign 语句的设计示例。
示例 #1:简单组合逻辑
下面代码实现简单数字组合逻辑,输出线网 z 通过 assign 语句持续驱动以实现数字方程。
module combo (
input a, b, c, d, e,
output z
);
assign z = ((a & b) | (c ^ d) & ~e);
endmodule
模块 combo 经综合工具展开为以下硬件原理图,可见组合逻辑用数字门实现。
测试平台
测试平台用于仿真验证设计行为是否符合预期。使用 for 循环和 10 时间单位延迟语句驱动所有输入组合到设计模块。
module tb;
reg a, b, c, d, e;
wire z;
integer i;
combo u0 ( .a(a), .b(b), .c(c), .d(d), .e(e), .z(z));
initial begin
a <= 0; b <= 0; c <= 0; d <= 0; e <= 0;
$monitor ("a=%0b b=%0b c=%0b d=%0b e=%0b z=%0b", a, b, c, d, e, z);
for (i = 0; i < 32; i = i + 1) begin
{a, b, c, d, e} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run a=0 b=0 c=0 d=0 e=0 z=0 a=0 b=0 c=0 d=0 e=1 z=0 a=0 b=0 c=0 d=1 e=0 z=1 ... a=1 b=1 c=1 d=1 e=1 z=1 ncsim: *W,RNQUIE: Simulation is complete.
注意:assign 和 always 两种方法综合出相同硬件逻辑。
示例 #2:半加器
半加器模块接受两个标量输入 a、b,用组合逻辑驱动输出 sum 和进位 cout。sum 由 a 和 b 异或驱动,cout 由两者与运算得出。
module ha (
input a, b,
output sum, cout
);
assign sum = a ^ b;
assign cout = a & b;
endmodule
测试平台
module tb;
reg a, b;
wire sum, cout;
integer i;
ha u0 ( .a(a), .b(b), .sum(sum), .cout(cout));
initial begin
a <= 0; b <= 0;
$monitor("a=%0b b=%0b sum=%0b cout=%0b", a, b, sum, cout);
for (i = 0; i < 4; i = i + 1) begin
{a, b} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run a=0 b=0 sum=0 cout=0 a=0 b=1 sum=1 cout=0 a=1 b=0 sum=1 cout=0 a=1 b=1 sum=0 cout=1 ncsim: *W,RNQUIE: Simulation is complete.
示例 #3:全加器
全加器可用上述半加器模块构建,或直接用 assign 语句驱动输出 sum 和 cout。
module fa (
input a, b, cin,
output sum, cout
);
assign sum = (a ^ b) ^ cin;
assign cout = (a & b) | ((a ^ b) & cin);
endmodule
测试平台
module tb;
reg a, b, cin;
wire sum, cout;
integer i;
fa u0 ( .a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
initial begin
a <= 0; b <= 0;
$monitor("a=%0b b=%0b cin=%0b sum=%0b cout=%0b", a, b, cin, sum, cout);
for (i = 0; i < 8; i = i + 1) begin
{a, b, cin} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run a=0 b=0 cin=0 sum=0 cout=0 a=0 b=0 cin=1 sum=1 cout=0 a=0 b=1 cin=0 sum=1 cout=0 a=0 b=1 cin=1 sum=0 cout=1 a=1 b=0 cin=0 sum=1 cout=0 a=1 b=0 cin=1 sum=0 cout=1 a=1 b=1 cin=0 sum=0 cout=1 a=1 b=1 cin=1 sum=1 cout=1 ncsim: *W,RNQUIE: Simulation is complete.
示例 #4:2x1 多路选择器
简单 2x1 多路选择器用三元运算符决定哪个输入赋给输出 c。sel 为 1 时输出 a,为 0 时输出 b。
module mux_2x1 (input a, b, sel, output c);
assign c = sel ? a : b;
endmodule
测试平台
module tb;
reg a, b, sel;
wire c;
integer i;
mux_2x1 u0 ( .a(a), .b(b), .sel(sel), .c(c));
initial begin
a <= 0; b <= 0; sel <= 0;
$monitor("a=%0b b=%0b sel=%0b c=%0b", a, b, sel, c);
for (i = 0; i < 3; i = i + 1) begin
{a, b, sel} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run a=0 b=0 sel=0 c=0 a=0 b=0 sel=1 c=0 a=0 b=1 sel=0 c=1 ncsim: *W,RNQUIE: Simulation is complete.
示例 #5:1x4 解多路器
解多路器用 sel 和 f 组合驱动不同输出信号。每个输出由单独 assign 语句驱动。注意一般不推荐同一信号被不同 assign 语句驱动。
module demux_1x4 (
input f,
input [1:0] sel,
output a, b, c, d
);
assign a = f & ~sel[1] & ~sel[0];
assign b = f & sel[1] & ~sel[0];
assign c = f & ~sel[1] & sel[0];
assign d = f & sel[1] & sel[0];
endmodule
测试平台
module tb;
reg f;
reg [1:0] sel;
wire a, b, c, d;
integer i;
demux_1x4 u0 ( .f(f), .sel(sel), .a(a), .b(b), .c(c), .d(d));
initial begin
f <= 0; sel <= 0;
$monitor("f=%0b sel=%0b a=%0b b=%0b c=%0b d=%0b", f, sel, a, b, c, d);
for (i = 0; i < 8; i = i + 1) begin
{f, sel} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run f=0 sel=0 a=0 b=0 c=0 d=0 f=0 sel=1 a=0 b=0 c=0 d=0 f=0 sel=10 a=0 b=0 c=0 d=0 f=0 sel=11 a=0 b=0 c=0 d=0 f=1 sel=0 a=1 b=0 c=0 d=0 f=1 sel=1 a=0 b=0 c=1 d=0 f=1 sel=10 a=0 b=1 c=0 d=0 f=1 sel=11 a=0 b=0 c=0 d=1 ncsim: *W,RNQUIE: Simulation is complete.
示例 #6:4x16 解码器
module dec_3x8 (
input en,
input [3:0] in,
output [15:0] out
);
assign out = en ? 1 << in: 0;
endmodule
测试平台
module tb;
reg en;
reg [3:0] in;
wire [15:0] out;
integer i;
dec_3x8 u0 ( .en(en), .in(in), .out(out));
initial begin
en <= 0; in <= 0;
$monitor("en=%0b in=0x%0h out=0x%0h", en, in, out);
for (i = 0; i < 32; i = i + 1) begin
{en, in} = i;
#10;
end
end
endmodule
仿真日志
ncsim> run en=0 in=0x0 out=0x0 en=0 in=0x1 out=0x0 ... en=1 in=0xf out=0x8000 ncsim: *W,RNQUIE: Simulation is complete.
Verilog