将if else语句转换为三元语句

时间:2010-05-05 16:21:07

标签: verilog

我使用ternary翻译了以下代码。但是,我知道它有问题。有人可以指出我正确的方向吗?

ForwardA = 0;
ForwardB = 0;

//EX Hazard
if (EXMEMRegWrite == 1) begin
 if (EXMEMrd != 0)
    if (EXMEMrd == IDEXrs)
        ForwardA = 2'b10;
   if (EXMEMrd == IDEXrt && IDEXTest == 0)
        ForwardB = 2'b10;
end


//MEM Hazard

if (MEMWBRegWrite == 1) begin
 if (MEMWBrd != 0) begin
    if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
            if (MEMWBrd == IDEXrs)
                ForwardA = 2'b01;
    if (IDEXTest == 0) begin
        if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
            if (MEMWBrd == IDEXrt)
                ForwardB = 2'b01;
    end
 end
end



ForwardA = (MEMWBRegWrite && MEMWBrd != 0 && (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs))) && (MEMWBrd == IDEXrs)) ?  
                                    2'b01 : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrs) ? 2'b10 : 0);

ForwardB = (IDEXTest == 0 && MEMWBRegWrite && MEMWBrd != 0 && (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt))) && (MEMWBrd == IDEXrs)) ?  
                                    2'b01 : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrt && IDEXTest == 0) ? 2'b10 : 0);

4 个答案:

答案 0 :(得分:10)

令人惊讶的是,我将冒险投票并告诉您正确方向是让您的代码处于相对可读的状态。

我怀疑你唯一能做的就是更糟糕的做法是将它作为正则表达式或将其转换为内联汇编: - )

转换的事实应该告诉你一些关于你正在尝试的智慧的事情。


根据您在其他地方的评论:

  

这是verilog,因此我需要在三元组中进行,并且不能有if else,否则我需要一个始终阻塞之前我不想要...我希望剩下的为0如果if else else中的所有条件都不满足

好吧,如果你必须这样做,反对我的建议(我并不是一个人在这里提供这个建议),这是你应该使用的方法(我不知道什么是“总是阻止“即便如此,我也没资格与你争论这一点。”

由于您当前的代码将ForwardAForwardB设置为值,然后仅在某些条件下更改它们,您可以通过撤消顺序将其转换为三元组。这是因为,在您的if版本中,以后的代码优先,但早期的代码优先于三元组。

找出ForwardAForwardB在什么情况下按相反顺序设置并重建这些条件。

这是您的原始代码,压缩了一下。我还将2'b10内容更改为2'b10',因此我们仍然可以在SO渲染引擎中获得良好的格式 - 不要忘记将其更改回来。

ForwardA = 0;
ForwardB = 0;
if (EXMEMRegWrite == 1) begin
 if (EXMEMrd != 0)
    if (EXMEMrd == IDEXrs)
        ForwardA = 2'b10';
   if (EXMEMrd == IDEXrt && IDEXTest == 0)
        ForwardB = 2'b10';
end
if (MEMWBRegWrite == 1) begin
 if (MEMWBrd != 0) begin
    if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
            if (MEMWBrd == IDEXrs)
                ForwardA = 2'b01';
    if (IDEXTest == 0) begin
        if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
            if (MEMWBrd == IDEXrt)
                ForwardB = 2'b01';
    end
 end
end

你可以看到B设置在三个地方。它在底部2'b01设置为if,在顶部设置为2'b10,在开始时设置为0。转换条件:

ForwardB = ((MEMWBRegWrite == 1) &&
            (MEMWBrd != 0) &&
            (IDEXTest == 0) &&
            (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt))) &&
            (MEMWBrd == IDEXrt))
            ? 2'b01'
            : ((EXMEMRegWrite == 1) &&
               (EXMEMrd != 0) &&
               (EXMEMrd == IDEXrt && IDEXTest == 0))
               ? 2'b10'
               : 0;

同样的A:

ForwardA = ((MEMWBRegWrite == 1) &&
            (MEMWBrd != 0) &&
            (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs))) &&
            (MEMWBrd == IDEXrs))
            ? 2'b01'
            : ((EXMEMRegWrite == 1) &&
               (EXMEMrd != 0) &&
               (EXMEMrd == IDEXrs))
               ? 2'b10'
               : 0;

现在这背后的理论是好的,但如果我在转录中犯了一个错误,或者如果Verilog只是厌恶地举手,拿起球,然后小跑,我就不会感到有点惊讶了。家: - )

我是否至少可以建议,如果你必须遵循这条道路,那么你们两个:

  • 尝试将三元表达式至少保留为 little 可读,并使用所有漂亮的空白区域和多行;和
  • 将原始代码保留在评论中,因此如果您遇到问题或想要更改逻辑,至少可以回复它?

说真的,你会在六个月的时间里再次感谢我,当你再次看到它时,试图找出你在想什么: - )

答案 1 :(得分:3)

您不需要这样做。将代码粘贴在“always @ *”块中,并将您指定的任何内容声明为“reg”。

reg [1:0] ForwardA;
reg [1:0] ForwardB;

always @(*) begin
   // Your combo logic here..
end

答案 2 :(得分:1)

好吧,假设您坚持以任何理由保持三元形式,如果您只是正确地格式化它,您的可读性会大大提高。

const bool cond1 = MEMWBRegWrite && MEMWBrd != 0 &&
                   !(EXMEMRegWrite == 1 && EXMEMrd != 0 && EXMEMrd == IDEXrs) &&
                   MEMWBrd == IDEXrs;
ForwardA = cond1
           ? 2'b01
           : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrs) ? 2'b10 : 0);

const bool cond2 = IDEXTest == 0 &&
                   MEMWBRegWrite && MEMWBrd != 0 &&
                   !(EXMEMRegWrite == 1 && EXMEMrd != 0 && EXMEMrd == IDEXrt) &&
                   MEMWBrd == IDEXrs;
ForwardB =  cond2
            ? 2'b01
            : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrt && IDEXTest == 0) ? 2'b10 : 0);

现在,该代码的格式就像它是C ++而不是你实际使用的那些,但是更容易弄清楚发生了什么。

但是,我会指出你的if语句不可能与你的三元表达式匹配。你的if语句没有else子句,三元句总是有else子句。但是,由于你的问题甚至没有完全清楚你是否试图将if语句转换为三元表达式或将三元表达式转换为if语句,因此有点难以准确地给出你想要的东西。

编辑:三元表达式总是同时包含if和else子句。你不能直接将没有else子句的if语句变成三元组,因为你没有三元组的else部分。现在,如果需要,可以在某些情况下提取一些技巧,比如将变量设置为自身。例如,

ForwardA = cond1 ? newValue : FordwardA;

你基本上是说不要改变else子句中的值 - 但这是假设你将结果赋给变量。表达式越复杂,就越难以实现这种技巧,并且代码变得越复杂。更不用说,取决于编译器执行或不执行的优化,它可以将变量分配给自身,这不是非常有效。

一般来说,将没有else子句的if语句翻译成三元表达式是一个坏主意。它只能通过提取技巧而不是直接说出你的意思来完成,而这只会让事情复杂化。而且这段代码很复杂。

我建议不要在这里使用三元,除非你真的需要它。如果你这样做,至少打破表达。即使你的三元表达式是正确的,它的很多比if语句更难阅读。

编辑2 :如果你真的需要这是一个三元表达式,那么我建议你坐下来弄清楚ForwardA应该是什么样的值和创建一个基于它的三元表达式,而不是试图直接转换你拥有的if语句(对于Forw​​ardB也是如此)。你的if-statments不仅要决定分配给每个变量的值,还要决定赋值给哪个变量,这会使事情变得相当复杂。

在其他语言中(我不知道verilog),你可以使用三元表达式来选择除了你在表达式右侧所做的任何事情之外还要赋值的变量,但是这样做了真的很复杂。最好创建一个临时文件,其中包含要分配的值,另一个三元文件用于确定将其分配给哪个变量。

不知道verilog,我真的不知道你能做什么,不能用if语句和三元表达式,但我认为必须有一个更好的方法来处理这个而不是使用三元组。也许不是,但你想要做的事情非常困难且容易出错。

答案 3 :(得分:1)

首先不要这样做!这样做没有意义。它不会编译为更好的代码,并且不太可读,正如您在尝试纠正它时所注意到的那样。如果你需要它作为表达式,最好将它编码为内联函数。