2

我已经使用三元翻译了以下代码。然而,我知道它有问题。有人可以指出我正确的方向吗?

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

4 回答 4

10

令人惊讶的是,我将冒着被否决的风险告诉你正确的方向是让你的代码保持相对可读的状态。

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

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


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

这是verilog,因此我需要在三元中执行它并且不能有if else,否则我需要一个always块并且我不想要那个......如果没有的话,我希望剩下的为0满足上述 if else 中的条件

好吧,如果你必须这样做,违背我的建议(我并不是唯一一个提供这个建议的人),这是你应该使用的方法(我不知道“总是阻止”是什么,所以我没有资格与你争论这一点)。

由于您当前的代码正在设置ForwardA和设置ForwardB值,然后仅在某些条件下更改它们,因此您可以通过反转顺序将其转换为三元。那是因为,在您的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在底部if2'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 只是厌恶地举起手,拿起球,然后小跑回家,我一点也不感到惊讶:- )

我至少可以建议,如果你必须走这条路,你们俩:

  • 尽量让三元表达式至少有一点可读性,留有漂亮的空白和多行;和
  • 将原始代码保留在注释中,以便在遇到问题或想要更改逻辑时至少可以返回到它?

说真的,六个月后你会感谢我的

于 2010-05-05T16:27:35.360 回答
3

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

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

always @(*) begin
   // Your combo logic here..
end
于 2010-05-07T10:48:56.140 回答
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 语句(ForwardB 也是如此)。您的 if 语句不仅决定为每个变量分配什么值,而且决定将该值分配给哪个变量,这使事情变得相当复杂。

在其他语言中(我不了解verilog),除了您在表达式右侧执行的任何操作之外,您还可以使用三元表达式来选择将值分配给哪个变量,但这变得非常复杂。最好创建一个临时变量来保存要分配的值和一个单独的三元组来确定将其分配给哪个变量。

不知道verilog,我真的不知道if语句和三元表达式可以做什么和不能做什么,但我认为必须有比使用三元更好的方法来处理这个问题。也许不是,但是您尝试做的事情非常困难且容易出错。

于 2010-05-05T16:37:05.197 回答
1

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

于 2010-05-05T17:04:40.963 回答