SystemVerilog 条件语句语法错误
SystemVerilog conditional statement syntax error
我正在尝试练习 SystemVerilog 并尝试基于此图实现 ALU(算术逻辑单元):
我在 EDA playground 上在线模拟 SystemVerilog 代码(https://www.edaplayground.com/x/mYi):
ALU:
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] f,
output [31:0] result,
);
/*000*/
if (f[0]==0 && f[1]==0 && f[2]===0)
begin
assign result = a & b;
end
/*001*/
else (f[0]==0 && f[1]==0 && f[2]==1)
begin
assign result = a | b;
end
/*010*/
else (f[0]==0 && f[1]==1 && f[2]==0)
begin
assign result = a + b;
end
/*011 not used*/
else (f[0]==0 && f[1]==1 && f[2]==1)
begin
assign result = -1;
end
/*100*/
else (f[0]==1 && f[1]==0 && f[2]==0)
begin
assign result = a & ~b;
end
/*101*/
else (f[0]==1 && f[1]==0 && f[2]==1)
begin
assign result = a | ~b;
end
/*110*/
else (f[0]==1 && f[1]==1 && f[2]==0)
begin
assign result = a - b;
end
/*111 slt*/
else
begin
assign result = -1;
end
endmodule
部分测试台:
module testharness();
reg [31:0] a;
reg [31:0] b;
reg [2:0] f;
reg [31:0] result;
//DUT (Device Under Test)
alu alu_0 (
.a (a),
.b (b),
.f (f),
.result (result)
);
// Test program
initial begin
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*0+0*/
a[0]=0;
b[0]=0;
$display( "a (%d) + b (%d) = %d%d%d%d", a[0], b[0], result[0], result[1]);
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*0+1*/
a[0]=0;
b[0]=1;
$display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*1+1*/
a[0]=1;
b[0]=1;
$display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
$finish;
end
endmodule
我一直收到这个错误:
错误 VCP2000 "Syntax error. Unexpected token: (. Expected tokens: '???' , ';' , 'always' , 'and' , 'assign' ... ." "design.sv" 15 9
这是行:
else (f[0]==0 && f[1]==0 && f[2]==1)
begin
assign result = a | b;
end
我没有看到任何明显的东西。
谢谢
我认为您使用 always
语句和连续赋值混淆了组合逻辑。正如其他用户之前提到的,我也认为如果您能看一下一些基本的 Verilog 教程会很好。 Asic-world.com 有一些很好的入门教程,例如 Deepak Kumar Tala 的 Verilog in One Day。
但是,让我试着向您解释一下。您在示例中使用的是 连续赋值语句 。您可以在 IEEE Std 1800-2012 的第 10.3.2 节中找到更多相关信息。手册说:
Assignments on nets or variables shall be continuous and automatic. In
other words, whenever an operand in the right-hand expression changes
value, the whole right-hand side shall be evaluated.
这里不是这种情况,因为所有赋值语句的右侧操作数都是相同的。它不是自动的,因为它取决于您的 if 语句。看看下面这个非常简单的例子。如果你总是希望 result
成为 a & b
,你可以使用下面的代码。但是,您可以想象,对于更复杂的逻辑,这会变得相当冗长。
module alu(
input [31:0] a,
input [31:0] b,
output [31:0] result,
);
assign result = (a & b);
endmodule
这就是 SystemVerilog 提供程序块的原因,例如 always
、always_comb
、always_latch
和 always_ff
(IEEE 标准 1800-2012 中的第 9 节)。对于您的示例,您应该使用 always_comb
。引用手册第9.2.2.2节:
SystemVerilog provides a special always_comb procedure for modeling
combinational logic behavior.
有了这个,我们可以将您的代码重写为
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] f,
output [31:0] result,
);
reg [31:0] result_;
always_comb
begin
/*000*/
if (f[0]==0 && f[1]==0 && f[2]===0)
begin
result_ = a & b;
end
/*001*/
else if (f[0]==0 && f[1]==0 && f[2]==1)
begin
result_ = a | b;
end
/*010*/
else if (f[0]==0 && f[1]==1 && f[2]==0)
begin
result_ = a + b;
end
/*011 not used*/
else if(f[0]==0 && f[1]==1 && f[2]==1)
begin
result_ = -1;
end
/*100*/
else if (f[0]==1 && f[1]==0 && f[2]==0)
begin
assign result = a & ~b;
end
/*101*/
else if (f[0]==1 && f[1]==0 && f[2]==1)
begin
result_ = a | ~b;
end
/*110*/
else if (f[0]==1 && f[1]==1 && f[2]==0)
begin
result_ = a - b;
end
/*111 slt*/
else
begin
result_ = -1;
end
end // End of always_comb
assign result = result_;
endmodule
请注意,您可以连续分配 wire
,但您需要将变量声明为 reg
才能在 always 块中使用它。这就是我使用 result_
而不是直接分配 result
的原因。在代码块的最后,我不断地将result_
赋值给result
。 Asic-world.com 也有关于 difference between regs and wires.
的教程
如果你不想考虑是使用reg
还是wire
,你也可以使用新关键字logic
。
编辑:正如 Oldfart 所指出的,我最初忘记修复您的 if...else 语句。在您的代码中,您总是使用 else
而不是 else if
。这可能也是编译器向您抛出错误的直接原因。
我正在尝试练习 SystemVerilog 并尝试基于此图实现 ALU(算术逻辑单元):
我在 EDA playground 上在线模拟 SystemVerilog 代码(https://www.edaplayground.com/x/mYi):
ALU:
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] f,
output [31:0] result,
);
/*000*/
if (f[0]==0 && f[1]==0 && f[2]===0)
begin
assign result = a & b;
end
/*001*/
else (f[0]==0 && f[1]==0 && f[2]==1)
begin
assign result = a | b;
end
/*010*/
else (f[0]==0 && f[1]==1 && f[2]==0)
begin
assign result = a + b;
end
/*011 not used*/
else (f[0]==0 && f[1]==1 && f[2]==1)
begin
assign result = -1;
end
/*100*/
else (f[0]==1 && f[1]==0 && f[2]==0)
begin
assign result = a & ~b;
end
/*101*/
else (f[0]==1 && f[1]==0 && f[2]==1)
begin
assign result = a | ~b;
end
/*110*/
else (f[0]==1 && f[1]==1 && f[2]==0)
begin
assign result = a - b;
end
/*111 slt*/
else
begin
assign result = -1;
end
endmodule
部分测试台:
module testharness();
reg [31:0] a;
reg [31:0] b;
reg [2:0] f;
reg [31:0] result;
//DUT (Device Under Test)
alu alu_0 (
.a (a),
.b (b),
.f (f),
.result (result)
);
// Test program
initial begin
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*0+0*/
a[0]=0;
b[0]=0;
$display( "a (%d) + b (%d) = %d%d%d%d", a[0], b[0], result[0], result[1]);
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*0+1*/
a[0]=0;
b[0]=1;
$display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
/*000*/
f[0]=0;
f[1]=1;
f[2]=0;
/*1+1*/
a[0]=1;
b[0]=1;
$display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
$finish;
end
endmodule
我一直收到这个错误:
错误 VCP2000 "Syntax error. Unexpected token: (. Expected tokens: '???' , ';' , 'always' , 'and' , 'assign' ... ." "design.sv" 15 9
这是行:
else (f[0]==0 && f[1]==0 && f[2]==1)
begin
assign result = a | b;
end
我没有看到任何明显的东西。
谢谢
我认为您使用 always
语句和连续赋值混淆了组合逻辑。正如其他用户之前提到的,我也认为如果您能看一下一些基本的 Verilog 教程会很好。 Asic-world.com 有一些很好的入门教程,例如 Deepak Kumar Tala 的 Verilog in One Day。
但是,让我试着向您解释一下。您在示例中使用的是 连续赋值语句 。您可以在 IEEE Std 1800-2012 的第 10.3.2 节中找到更多相关信息。手册说:
Assignments on nets or variables shall be continuous and automatic. In other words, whenever an operand in the right-hand expression changes value, the whole right-hand side shall be evaluated.
这里不是这种情况,因为所有赋值语句的右侧操作数都是相同的。它不是自动的,因为它取决于您的 if 语句。看看下面这个非常简单的例子。如果你总是希望 result
成为 a & b
,你可以使用下面的代码。但是,您可以想象,对于更复杂的逻辑,这会变得相当冗长。
module alu(
input [31:0] a,
input [31:0] b,
output [31:0] result,
);
assign result = (a & b);
endmodule
这就是 SystemVerilog 提供程序块的原因,例如 always
、always_comb
、always_latch
和 always_ff
(IEEE 标准 1800-2012 中的第 9 节)。对于您的示例,您应该使用 always_comb
。引用手册第9.2.2.2节:
SystemVerilog provides a special always_comb procedure for modeling combinational logic behavior.
有了这个,我们可以将您的代码重写为
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] f,
output [31:0] result,
);
reg [31:0] result_;
always_comb
begin
/*000*/
if (f[0]==0 && f[1]==0 && f[2]===0)
begin
result_ = a & b;
end
/*001*/
else if (f[0]==0 && f[1]==0 && f[2]==1)
begin
result_ = a | b;
end
/*010*/
else if (f[0]==0 && f[1]==1 && f[2]==0)
begin
result_ = a + b;
end
/*011 not used*/
else if(f[0]==0 && f[1]==1 && f[2]==1)
begin
result_ = -1;
end
/*100*/
else if (f[0]==1 && f[1]==0 && f[2]==0)
begin
assign result = a & ~b;
end
/*101*/
else if (f[0]==1 && f[1]==0 && f[2]==1)
begin
result_ = a | ~b;
end
/*110*/
else if (f[0]==1 && f[1]==1 && f[2]==0)
begin
result_ = a - b;
end
/*111 slt*/
else
begin
result_ = -1;
end
end // End of always_comb
assign result = result_;
endmodule
请注意,您可以连续分配 wire
,但您需要将变量声明为 reg
才能在 always 块中使用它。这就是我使用 result_
而不是直接分配 result
的原因。在代码块的最后,我不断地将result_
赋值给result
。 Asic-world.com 也有关于 difference between regs and wires.
如果你不想考虑是使用reg
还是wire
,你也可以使用新关键字logic
。
编辑:正如 Oldfart 所指出的,我最初忘记修复您的 if...else 语句。在您的代码中,您总是使用 else
而不是 else if
。这可能也是编译器向您抛出错误的直接原因。