使用条件操作时出现错误
I'm getting error when I use conditional operation
我使用条件运算符写了一行,如下所示:
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00? (!DisI? {rs2, rs1} : 64'bz) : (RdEn==2'b01? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn}))) : 64'bz;
- RS2 & RS1为32位输出线。
- Rn & Rm 是 32 位输入。
- rs1 和 rs2 是 32 位寄存器。
- RdEn为2bit寄存器
- DisI和switch是一位寄存器。
模拟器(Icarus 0.9.7 或任何)显示上述行中存在语法错误。
这是解决相同问题的我的代码:
module TEST(Rn, Rm, DisM, DisX, DisI, switch, RdEn, RS1, RS2);
input [31:0]Rn, Rm;
input DisM, DisX, DisI, switch;
input [1:0]RdEn;
output [31:0]RS1, RS2;
reg [31:0]rs1, rs2;
always@*
begin
rs1 = Rn + 32'd7;
rs2 = Rm - 32'd7;
end
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00? (!DisI? {rs2, rs1} : {64{1'bz}}) : (RdEn==2'b01? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn}))) : {64{1'bz}};
endmodule
编译器将 RdEn==2'b00?
中的 ?
解释为第 3 位而不是三元运算符。只需在 b00
和 ?
之间添加一个 space。 b01?
.
相同
?
是有效的 z_digit。请参阅 IEEE 标准 1800-2012,第 5.7 节数字。
此外,您的括号数量不匹配(优秀的编辑器可以证明这一点):
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00 ? (!DisI? {rs2, rs1} : {64{1'bz}}) : (RdEn==2'b01 ? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn})) : {64{1'bz}};
使用 {64{1'bz}}
确保获得 64 位的 1'bz
也是一个好习惯。
虽然您已经获得了可接受的答案,但我强烈建议您重新编码作业。照原样,它很难阅读,因此也很难调试。至少添加 return 行并缩进,这样条件很容易在视觉上配对。例如,以下是添加了换行符和空格的 toolic 解决方案的副本。请注意 RdEn==2'b00?
问题如何不会发生在这种格式样式下。像 emacs 和 vim 这样的编辑器有语法插件可以帮助缩进格式。
assign {RS2, RS1} = (!DisM || !DisX)
? (RdEn==2'b00
? (!DisI ? {rs2, rs1} : {64{1'bz}})
: (RdEn==2'b01
? (!switch ? {rs2, Rn} : {Rn, rs1})
: {Rm, Rn}))
: {64{1'bz}};
在实践中,我发现条件运算符 ?:
(w/o high-Z)通常会在合成时显式 2:1 多路复用器,这可能不是时序和面积的最佳选择。我还发现保持三态分配简单可以得到更清晰的结果。
我通常推荐的方法是确定与三态分配分开的输出使能和输出数据。合成器通常用这种方法比一个长赋值语句做得更好;至少从我的经验来看。如果您的三态驱动器数量有限,这种方法也很好,这在 FPGA 中很常见。
wire out_en = (!DisM || !DisX) && !(RdEn==2'b00 && !DisI);
reg [63:0] out_data;
always @* begin
case(RdEn)
2'b00 : out_data = {rs2, rs1};
2'b01 : out_data = !switch ? {rs2, Rn} : {Rn, rs1});
default : out_data = {Rm, Rn};
endcase
end
assign {RS2, RS1} = out_en ? out_data : {64{1'bz}};
有时,具有非重叠使能的并行三态驱动器在满足某些设计标准方面做得更好。这种方法可以根据技术节点和架构减少时序。通常会有一个区域命中,如果加载太多,它可能会对时间产生负面影响。
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b00 && !DisI) ? {rs2, rs1} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b01 && !switch) ? {rs2, Rn} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b01 && switch) ? { Rn, rs1} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn[1]) ? { Rm, Rn} : {64{1'bz}};
无论使用何种方法,请确保三态的启用控制无毛刺。如果信号不干净,可能会导致总线争用。理想情况下,使能信号应该是直接触发器。失败的启用信号在实践中并不总是可行的,因此您需要密切关注它。您通常不会在 RTL 仿真中看到潜在的故障。如果有问题,您的综合报告可能会有一些见解。
我使用条件运算符写了一行,如下所示:
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00? (!DisI? {rs2, rs1} : 64'bz) : (RdEn==2'b01? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn}))) : 64'bz;
- RS2 & RS1为32位输出线。
- Rn & Rm 是 32 位输入。
- rs1 和 rs2 是 32 位寄存器。
- RdEn为2bit寄存器
- DisI和switch是一位寄存器。
模拟器(Icarus 0.9.7 或任何)显示上述行中存在语法错误。
这是解决相同问题的我的代码:
module TEST(Rn, Rm, DisM, DisX, DisI, switch, RdEn, RS1, RS2);
input [31:0]Rn, Rm;
input DisM, DisX, DisI, switch;
input [1:0]RdEn;
output [31:0]RS1, RS2;
reg [31:0]rs1, rs2;
always@*
begin
rs1 = Rn + 32'd7;
rs2 = Rm - 32'd7;
end
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00? (!DisI? {rs2, rs1} : {64{1'bz}}) : (RdEn==2'b01? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn}))) : {64{1'bz}};
endmodule
编译器将 RdEn==2'b00?
中的 ?
解释为第 3 位而不是三元运算符。只需在 b00
和 ?
之间添加一个 space。 b01?
.
?
是有效的 z_digit。请参阅 IEEE 标准 1800-2012,第 5.7 节数字。
此外,您的括号数量不匹配(优秀的编辑器可以证明这一点):
assign {RS2, RS1} = (!DisM || !DisX)? (RdEn==2'b00 ? (!DisI? {rs2, rs1} : {64{1'bz}}) : (RdEn==2'b01 ? (!switch? {rs2, Rn} : {Rn, rs1}) : {Rm, Rn})) : {64{1'bz}};
使用 {64{1'bz}}
确保获得 64 位的 1'bz
也是一个好习惯。
虽然您已经获得了可接受的答案,但我强烈建议您重新编码作业。照原样,它很难阅读,因此也很难调试。至少添加 return 行并缩进,这样条件很容易在视觉上配对。例如,以下是添加了换行符和空格的 toolic 解决方案的副本。请注意 RdEn==2'b00?
问题如何不会发生在这种格式样式下。像 emacs 和 vim 这样的编辑器有语法插件可以帮助缩进格式。
assign {RS2, RS1} = (!DisM || !DisX)
? (RdEn==2'b00
? (!DisI ? {rs2, rs1} : {64{1'bz}})
: (RdEn==2'b01
? (!switch ? {rs2, Rn} : {Rn, rs1})
: {Rm, Rn}))
: {64{1'bz}};
在实践中,我发现条件运算符 ?:
(w/o high-Z)通常会在合成时显式 2:1 多路复用器,这可能不是时序和面积的最佳选择。我还发现保持三态分配简单可以得到更清晰的结果。
我通常推荐的方法是确定与三态分配分开的输出使能和输出数据。合成器通常用这种方法比一个长赋值语句做得更好;至少从我的经验来看。如果您的三态驱动器数量有限,这种方法也很好,这在 FPGA 中很常见。
wire out_en = (!DisM || !DisX) && !(RdEn==2'b00 && !DisI);
reg [63:0] out_data;
always @* begin
case(RdEn)
2'b00 : out_data = {rs2, rs1};
2'b01 : out_data = !switch ? {rs2, Rn} : {Rn, rs1});
default : out_data = {Rm, Rn};
endcase
end
assign {RS2, RS1} = out_en ? out_data : {64{1'bz}};
有时,具有非重叠使能的并行三态驱动器在满足某些设计标准方面做得更好。这种方法可以根据技术节点和架构减少时序。通常会有一个区域命中,如果加载太多,它可能会对时间产生负面影响。
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b00 && !DisI) ? {rs2, rs1} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b01 && !switch) ? {rs2, Rn} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn==2'b01 && switch) ? { Rn, rs1} : {64{1'bz}};
assign {RS2, RS1} = ((!DisM || !DisX) && RdEn[1]) ? { Rm, Rn} : {64{1'bz}};
无论使用何种方法,请确保三态的启用控制无毛刺。如果信号不干净,可能会导致总线争用。理想情况下,使能信号应该是直接触发器。失败的启用信号在实践中并不总是可行的,因此您需要密切关注它。您通常不会在 RTL 仿真中看到潜在的故障。如果有问题,您的综合报告可能会有一些见解。