converting if else statement to ternary - verilog

I have translated the following code using ternary. However, I knew there was something wrong with it. Can someone please point me into the right direction?
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);

Surprisingly enough, I'm going to risk downvotes and tell you that the right direction is to leave your code in its relatively readable state.
I suspect the only thing you could do that would be worse would be to do it as a regular expression or convert it to inline assembly :-)
The fact that it's not converting easily should tell you something about the wisdom in what you're attempting.
Based on your comment elsewhere:
This is verilog and therefore I need to do it in ternary and can't have an if else, otherwise I would need an always block before and I don't want that... I want the remaining to be 0 if none of the conditions in the if else above is satisfied
Well, if you must do it, against my advice (and I'm not alone here in offering this advice), here's the method you should use (I have no idea what an "always block" even is so I'm not qualified to argue the point with you).
Since your current code is setting ForwardA and ForwardB to values then only changing them under certain conditions, you can transform that into a ternary by reversing the order. That's because, in your if version, later code takes precedence but earlier code takes precedence in the ternary.
Find out under what circumstances ForwardA and ForwardB are set in reverse order and reconstruct those conditions.
Here's your original code, compressed a bit. I've also changed your 2'b10 things into 2'b10' so we still get nice formatting in the SO rendering engine - don't forget to change them back.
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
You can see B is set in three places. It's set to 2'b01 in the bottom if, 2'b10 in the top one and 0 at the start. Converting the conditions:
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;
Similarly for 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;
Now the theory behind that is good but I wouldn't be the least bit surprised if I'd made an error in the transcription, or if Verilog just threw its hands up in disgust, picked up its ball, and trotted off home :-)
Can I at least suggest, if you must follow this path, you both:
try to leave the ternary expressions at least a little readable, with all that nice white space and multiple lines; and
keep the original code in a comment so at least you can go back to it if you have problems or want to change the logic?
Seriously, you'll thank me in six months time when you're looking over this again, trying to figure out what on Earth you were thinking :-)

You don't need to do this. Stick the code in an 'always #*' block, and declare anything you're assigning to as 'reg'.
reg [1:0] ForwardA;
reg [1:0] ForwardB;
always #(*) begin
// Your combo logic here..
end

First don't do it! there's no point, in doing so. It doesn't compile to better code and is less readable, as you noticed in your tries to correct it. If you need it as an expression it would be better to code it as an inline function.

Well, assuming that you insist on keeping it in ternary form for whatever reason, your readability would go up considerably if you'd just format it correctly.
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);
Now, that code is formatted as if it were C++ rather than whatever you're actually using, but it becomes much easier to figure out what's going on.
However, I would point out that your if-statements can't possibly match your ternary expressions. Your if statements have no else clause, and ternary expressions always have else clauses. However, since your question doesn't even make it entirely clear whether you're trying to convert the if-statements into ternary expressions or the ternary expressions into if-statements, it's a bit hard to give you exactly what you want.
EDIT: Ternary expressions always have both an if and an else clause. You cannot directly turn an if statement without an else clause into a ternary because you wouldn't have the else portion of the ternary. Now, you can pull some tricks in some cases if you need to, like setting a variable to itself. For instance,
ForwardA = cond1 ? newValue : FordwardA;
You're basically saying not to change the value in the else clause - but that's assuming that you're assigning the result to a variable. The more complicated the expression, the harder it is to pull that sort of trick, and the more convoluted the code becomes when you do. Not to mention, depending on what optimizations that the compiler does or doesn't do, it could be assigning the variable to itself, which isn't terribly efficient.
Generally-speaking, translating if-statements with no else clauses into ternary expressions is a bad idea. It can only be done by pulling tricks rather than directly saying what you mean, and it just complicates things. And this code is complicated enough as it is.
I'd advise not using a ternary here unless you really need it. And if you do, at least break down the expression. Even if your ternary expression were correct, it's much harder to read than the if-statements.
EDIT 2: If you really do need this to be a ternary expression, then I'd advise that you sit down and figure out the exact conditions under which ForwardA should be what set of values and create a ternary expression based on that rather than trying to directly convert the if-statements that you have (and the same for ForwardB). Your if-statments are not only deciding what value to assign to each variable, but which variable to assign that value to, and that complicates things considerably.
In other languages (I don't know about verilog), you can use a ternary expression for choosing which variable to assign the value to in addition to whatever you're doing on the right side of the expression, but that's getting really complicated. It might be best to create a temporary which holds the value which is to be assigned and a separate ternary to determine which variable to assign it to.
Not knowing verilog, I really don't know what you can and can't do with if-statements and ternary expression, but I would think that there's got to be a better way to handle this than using a ternary. Maybe not, but what you're trying to do is very difficult and error-prone.

Related

I need help understanding why my if statement is executing

I am having a hard time understanding why my first if statement is executing if my string variable exam1ScoreKnown is assigned the string "YES" or "Y". I only want the if statement to execute if the string is anything other than "YES" or "Y". Also, I have checked to make sure the variable is assigned "YES" or "Y" right before the if statement.
if (exam1ScoreKnown != "YES" || exam1ScoreKnown != "Y") {
totalWeight = totalWeight - exam1Weight - exam2Weight - finalExamWeight;
}
else if (exam2ScoreKnown != "YES" || exam2ScoreKnown != "Y") {
totalWeight = totalWeight - exam2Weight - finalExamWeight;
}
else if (finalExamScoreKnown != "YES" || finalExamScoreKnown != "Y") {
totalWeight = totalWeight - finalExamWeight;
}
This Boolean expression
(exam1ScoreKnown != "YES" || exam1ScoreKnown != "Y")
is equivalent to
!(exam1ScoreKnown == "YES" && exam1ScoreKnown == "Y")
I think in this rewritten form it is easier to see that it is a tautology, ie it is true every which way. I think you need to replace the or by and.

Translate conditional operators in Verilog

I'm just starting out with verilog and came across this piece of code on a project I was looking at. I'm having a hard time wrapping my head around it even after looking up the meaning of the operators.
assign sec_next = (clr || sec_reg == divisor && (state_reg == on)) ? 4'b0 : (state_reg == on) ? sec_reg + 1 : sec_reg;
Could someone maybe translate it to if else statements so I could understand?
always#* begin
if(clr || (sec_reg == divisor)&&(state_reg == on))
sec_next = 4'b0;
else if((state_reg == on))
sec_next = sec_reg + 1;
else sec_next = sec_reg;
end
Hope this will clear your doubt!! learn about the ternary operator in verilog.

what can I do to my code donĀ“t delete a 0 in a array?

I'm trying to make a calculator in Haxe, it is almost done but have a bug. The bug is happening every time that some part of the equation result in 0.
This is how I concatenate the numbers and put i the array number, the cn is the variable used to receive the digit and transform in a number, the ci is a specific counter to make the while work well and the c is the basic counter that is increased to a background while used to read the array (input) items:
var cn = '';
var ci = c;
if (input[c] == '-') {
number.push('+');
cn = '-';
ci ++;
}
while (input[ci] == '0' || input[ci] == '1' || input[ci] == '2' || input[ci] == '3' || input[ci] == '4' || input[ci] == '5' || input[ci] == '6' || input[ci] == '7' || input[ci] == '8' || input[ci] == '9' || input[ci] == '.') {
if(ci == input.length) {
break;
}
cn += input[ci];
ci++;
}
number.push(cn);
c += cn.length;
This is the part of the code used to calculate the addition and subtraction
for (i in 0 ... number.length) { trace(number); if (number[c] == '+') { number[c-1] = ''+(Std.parseFloat(number[c-1])+Std.parseFloat(number[c+1])); number.remove(number[c+1]); number.remove(number[c]); }
else {
c++;
}
}
Example:
12+13-25+1: When my code read this input, it transform in a array ([1,2,+,1,3,-,2,5,+,1]), then the code concatenate the numbers ([12,+,13,-,25,+,1]) and for lastly it seeks for the operators(+,-,* and /) to make the operation (ex: 12+13), substituting "12" for the result of the operation (25) and removing the "+" and the "13". This part works well and then the code does 25-25=0.
The problem starts here because the equation then becomes 0+1 and when the code process that what repend is that the 0 vanish and the 1 is removed and the output is "+" when the expected is "1".
remove in this case uses indexOf and is not ideal, suggest using splice instead.
number.splice(c,1);
number.splice(c,1);
https://try.haxe.org/#D3E38

Method inside of a class always returns same output while the same logic outside of the class works

I have this block of code inside of a class. No matter what data I pass into the class, this will always return "Loss".
def win_loss_unadj(self):
if self.side == "Long" and (self.getMAE > self.getStop) and (self.getMFE >= self.unadj_T2):
return "T2_Win"
elif self.side == "Long" and (self.getMAE > self.getStop) and (self.getMFE >= self.unadj_T1):
return "Win"
elif self.side == "Short" and (self.getMAE < self.getStop) and (self.getMFE <= self.unadj_T2):
return "T2_Win"
elif self.side == "Short" and (self.getMAE < self.getStop) and (self.getMFE <= self.unadj_T1):
return "Win"
else:
return "Loss"
When I use the same logic outside of the class (using print() instead of return), I get the correct results with the same data.
for i in range(len(tradeList)):
if Trade.side(tradeList[i]) == "Long" and (Trade.getMAE(tradeList[i]) > Trade.getStop(tradeList[i])) and (Trade.getMFE(tradeList[i]) >= Trade.unadj_T2(tradeList[i])):
print("T2_Win")
elif Trade.side(tradeList[i]) == "Long" and (Trade.getMAE(tradeList[i]) > Trade.getStop(tradeList[i])) and (Trade.getMFE(tradeList[i]) >= Trade.unadj_T1(tradeList[i])):
print("Win")
elif Trade.side(tradeList[i]) == "Short" and (Trade.getMAE(tradeList[i]) < Trade.getStop(tradeList[i])) and (Trade.getMFE(tradeList[i]) <= Trade.unadj_T2(tradeList[i])):
print("T2_Win")
elif Trade.side(tradeList[i]) == "Short" and (Trade.getMAE(tradeList[i]) < Trade.getStop(tradeList[i])) and (Trade.getMFE(tradeList[i]) <= Trade.unadj_T1(tradeList[i])):
print("Win")
else:
print("Loss")
Now, I might be grossly misunderstanding the return command or class methods in general. I am not experienced with python at all and for the life of me I can't figure out what's wrong here.
I checked if there was something wrong with the objects themselves, but there isn't. All the data is correct, so the issue MUST be in the first section of code I posted.

Is it possible to simplify this IF conditional statement in Verilog?

I'm was trying to create a binary counter, but when I simplified the IF statement, it stopped to work.
This code works:
if(counter<500000)
counter<=counter+1;
else
counter<=0;
if (counter==0)
if(LEDR<262143)
LEDR <= LEDR+1;
else
LEDR<=0;
this doesn't :
if(counter<500000)
counter<=counter+1;
else
counter<=0;
if (counter==0 && LEDR<262143)
LEDR <= LEDR+1;
else
LEDR<=0;
The two versions of your code are not equivalent.
In your original version, the else part is contained inside the counter == 0 condition, and will be executed when counter == 0 and LEDR >= 262143:
if (counter==0)
if(LEDR<262143)
LEDR <= LEDR+1;
else // counter must be 0 here
LEDR<=0;
In the "simplified" version, the else part will be executed when the opposite of counter == 0 && LEDR < 262143 is true, which is the case if counter != 0 or LEDR >= 262143.
if (counter==0 && LEDR<262143)
LEDR <= LEDR+1;
else // counter could be different from 0
LEDR<=0;
You can visualize the difference by listing all possible combinations in a table:
counter == 0 | LEDR < 262143 | LEDR <= 0 executed | LEDR <= LEDR+1 executed
| | orig. new | orig. new
-------------+---------------+--------------------+------------------------
false | false | no *yes* | no no
false | true | no *yes* | no no
true | false | yes yes | no no
true | true | no no | yes yes
As you can see, the new version behaves differently when counter != 0.
Actually, it is not possible to simplify the desired behaviour to a single if-else statement, because this would mean that you can only distinguish between the two cases of executing either LEDR <= LEDR + 1 or LEDR <= 0. But in the original code there is a third case (when counter != 0) where you execute nothing at all and leave LEDR untouched.
if (counter==0)
if(LEDR<262143)
LEDR <= LEDR+1;
else
LEDR<=0;
versus
if (counter==0 && LEDR<262143)
LEDR <= LEDR+1;
else
LEDR<=0;
The first condition for both is the same but you have altered the condition for the second argument.
First example is if ((counter==0) && !(LEDR<262143))
Second example is if !(counter==0 && LEDR<262143)
Using de-morgans law the second example could be:
if (counter!=0 || !(LEDR<262143) ) or
if (counter!=0 || (LEDR=<262143))
Therefore the if statement is not simplified but functionally different.

Resources