Translate conditional operators in Verilog - 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.

Related

why I get Syntax error near "else" in assertion in verilog?

I am trying to run a testbench which was written for a neuromorphic chip named ODIN.
Irun this code in Xilinx ISE. I get some errors that do not make sense. here is a part of code:
$display("----- Starting verification of programmed SNN parameters");
assert(snn_0.spi_slave_0.SPI_GATE_ACTIVITY == 1'b1) else $fatal(0, "SPI_GATE_ACTIVITY parameter not correct.");
assert(snn_0.spi_slave_0.SPI_OPEN_LOOP == `SPI_OPEN_LOOP ) else $fatal(0, "SPI_OPEN_LOOP parameter not correct.");
assert(snn_0.spi_slave_0.SPI_SYN_SIGN == `SPI_SYN_SIGN ) else $fatal(0, "SPI_SYN_SIGN parameter not correct.");
assert(snn_0.spi_slave_0.SPI_BURST_TIMEREF == `SPI_BURST_TIMEREF ) else $fatal(0, "SPI_BURST_TIMEREF parameter not correct.");
assert(snn_0.spi_slave_0.SPI_OUT_AER_MONITOR_EN == `SPI_OUT_AER_MONITOR_EN ) else $fatal(0, "SPI_OUT_AER_MONITOR_EN parameter not correct.");
assert(snn_0.spi_slave_0.SPI_AER_SRC_CTRL_nNEUR == `SPI_AER_SRC_CTRL_nNEUR ) else $fatal(0, "SPI_AER_SRC_CTRL_nNEUR parameter not correct.");
assert(snn_0.spi_slave_0.SPI_MONITOR_NEUR_ADDR == `SPI_MONITOR_NEUR_ADDR ) else $fatal(0, "SPI_MONITOR_NEUR_ADDR parameter not correct.");
assert(snn_0.spi_slave_0.SPI_MONITOR_SYN_ADDR == `SPI_MONITOR_SYN_ADDR ) else $fatal(0, "SPI_MONITOR_SYN_ADDR parameter not correct.");
assert(snn_0.spi_slave_0.SPI_UPDATE_UNMAPPED_SYN == `SPI_UPDATE_UNMAPPED_SYN ) else $fatal(0, "SPI_UPDATE_UNMAPPED_SYN parameter not correct.");
assert(snn_0.spi_slave_0.SPI_PROPAGATE_UNMAPPED_SYN == `SPI_PROPAGATE_UNMAPPED_SYN) else $fatal(0, "SPI_PROPAGATE_UNMAPPED_SYN parameter not correct.");
assert(snn_0.spi_slave_0.SPI_SDSP_ON_SYN_STIM == `SPI_SDSP_ON_SYN_STIM ) else $fatal(0, "SPI_SDSP_ON_SYN_STIM parameter not correct.");
I get this error for each line:
Syntax error near "else".
In our simple case for simulation with verilog v2k you can use $display to print a message:
always #* begin
$display("----- Starting verification of programmed SNN parameters");
if(snn_0.spi_slave_0.SPI_GATE_ACTIVITY != 1'b1)
$display("fatal: SPI_GATE_ACTIVITY parameter not correct.");
...
end
To sum it up, Xilinx ISE does not support SystemVerilog, so we can not use assertion.
To run this testbench I have to use Xilinx Vivado. Another way is to implement some function equivalent to assertion in verilog. Look at these answers at "Assert statement in Verilog"

Verilog modulus operator for wrapping around a range

My background is in software and I'm new to (System)Verilog so when tasked with implementing a caesar shifter (shift each letter in a string by N letters, wrapping around if necessary e.g. ABCXYZ shifted by 3 becomes DEFABC), I wrote the following, hoping to be able to reduce code duplication, like I would in software:
/* every variable except 'direction' has the type 'byte' */
always_comb
begin
shifted_char = fresh_char; /* don't touch bytes that aren't letters */
is_lower_case = "z" >= fresh_char && fresh_char >= "a";
is_upper_case = "Z" >= fresh_char && fresh_char >= "A";
if (is_lower_case || is_upper_case)
begin
unique if (is_lower_case)
alphabet_start = "a";
else if (is_upper_case)
alphabet_start = "A";
alphabet_position = fresh_char - alphabet_start;
if (direction == "f") /* direction is a module parameter: f for forwards results in a shifter, any other value results in an 'unshifter' */
new_alphabet_position = (26 + (alphabet_position + shift_by)) % 26;
else
new_alphabet_position = (26 + (alphabet_position - shift_by)) % 26;
shifted_char = new_alphabet_position + alphabet_start;
end
end
My question is (assuming it's a forward shifter): regarding the "% 26" part, can I expect the synthesizer to deduce that the range of possible values it's going to get at that point is [26, 26+25+25] ([26, 76]) and so there's only 2 cases the logic needs to distinguish between (>26 and >52), rather than [whatever is the smart call when having handle all possible 256 different inputs - (would it be to consider the cases >26, >52, >78 etc...? Or is there a better way? I digress...)]?
I could always do the following:
new_alphabet_position = alphabet_position + shift_by;
if (new_alphabet_position > 25)
new_alpahbet_position -= 26;
/* Or, for the reverse shifter: */
new_alphabet_position = alphabet_position - shift_by;
if (new_alphabet_position < 0)
new_alpahbet_position += 26;
...but was curious and wanted to ask that, as well as a related one (that I expect more people will be able to answer): Can it be used to make a normal non-power-of-2 counter (e.g.
count <= (count + 1) % 6;
)? Going by hgleamon1's response to the following thread, it seems as though (at least one) VHDL synth tool might interpret it as intended: https://forums.xilinx.com/t5/Synthesis/Modulus-synthesizable-or-non-synthesizable/td-p/747493
Unless there is a specialized macro cell, non powers of 2 modulus will take a large number of gates and have relatively long propagation delays especially if done as pure combiantional logic.
Be aware depending on your synthesizer the variables 'alphabet_start', 'alphabet_position', and 'new_alphabet_position' my be inferred latches. The way you used them is as intermediated logic, so if you don't references them outside this always block and your synthesizer has decent optimization, then it will not be a latch. To guarantee they will not be latches, they must be given default values outside the if statement.
You state that all variables except 'direction' are type 'byte', this means 'shift_by' may have a value greater than 25 or less than -25 ('byte' is a signed value by default). By using a signed values and adding three value (26 + (alphabet_position + shift_by)) before using the modulus, there is a decent changes that the mod26 will be evaluated on a 10-bit signed value. That will use more logic than if used on an 8-bit value. There is a change your synthesizer may do some optimization, but it might not be great.
If you can guarantee 'shift_by' is less than 26 and greater than -26 ( greater or equal to 0 if unsigned), then you don't need 'alphabet_position' or 'new_alphabet_position'. Simply add or subtract the 'shift_by' and calculate if out of range. For the range check, fist check if 8'(shifted_char-26) >= alphabet_start. The reason for this is to make sure we are comparing positive numbers. "z"+25 is 147 which is negative for a signed 8-bit value. The 8'() with cast it as an 8-bit unsigned value to trim any non-zero intermediate 9th+ bit(s). If an adjustment is not needed then check if hifted_char < alphabet_start as now the possibility of overflowing to a negative number has been already handled.
If you cannot guarantee 'shift_by' is within range, then you have no choose by to mod it. Luckily this is an 8-bit signed value which is better than your original worse case with a 10-bit signed value. This is not ideal but the best I can offer. It is more optimal to have the driver of 'shift_by' assign a legal value then adding more logic to mod it.
Since you are using SystemVerilog, you may want to consider using fresh_char inside { ["A":"Z"] } which is functionally the same as "Z" >= fresh_char && fresh_char >= "A". The inside is keyword is intended to be synthesizable, but I don't know if it is commonly supported.
Consider the following code. It may not be the most optimized, but it is more optimized than your original code:
always_comb
begin
shift_by_mod26 = shift_by % 26; // %26 is not need if guaranteed asb(value) < 26
alphabet_start = (fresh_char inside { ["A":"Z"] }) ? "A" : "a";
if ( fresh_char inside { ["A":"Z"], ["a":"z"] } )
begin
if (direction == "f")
shifted_char = fresh_char + shift_by_mod26;
else
shifted_char = fresh_char - shift_by_mod26;
// subtract 26 first in case shifted_char is >127
// bring back to a positive if signed (>127 unsigned is negative signed)
if (8'(shifted_char-26) >= alphabet_start)
shifted_char -= 26;
else if (shifted_char < alphabet_start)
shifted_char += 26;
end
else
begin
/* don't touch bytes that aren't letters */
shifted_char = fresh_char;
end
end
Note: if 'direction' is not a type 'byte', then it must be at least a 7bits(unsigned) wide or greater (sign agnostic) to every match "f"
Cross post answer for a cross post question

How to check for unknown registers in verilog

When getting three inputs from the console, I am wondering how to check and 'warn' the user that a register may not have been initialized.
to do this I am trying:
flag = $value$plusargs("a=%b", a);
if (flag != 0 && flag != 1) begin
$display("a might not be initialized");
end
flag = $value$plusargs("b=%b", b);
flag = $value$plusargs("c=%b", c);
#1 $display("a=%b b=%b c=%b z=%b", a, b, c, z);
However with my limited knowledge I am having a difficult time figuring out what to do. When I run my compiled code with no paramaters I get:
a = x, b = x, c = x, z = x;
but no warning, even though the flag(a) is clearly not 1 and not 0
flag returns true(1) if $value$plusargs finds +a=value on the command line and sets the value of a. So you want
if (flag == 0) begin
$display("a might not be initialized");
You can do this in one step
if ( !$value$plusargs("a=%b", a) ) begin
$display("a might not be initialized");
And if you use SystemVerilog, you can use $warning() instead of $display().
To compare with unknown value, you should use !== or === instead of != and ==

Modifying strings in emu8086 assembly

I currently working on an intro assignment for a computer architecture course and i was asked to accomplish some string modifications. My question is not how to do it, but what should i be researching to be able to do it? Is there any functions that will make this easier, for example .reverse() is java.
What i need to accomplish is getting string input from the user, reverse the letters (while reversing numbers keep them where they are), add spaces whenever there is a vowel, and alternate the caps.
Example:
Input: AbC_DeF12
Output: f E d _ c B a 2 1
This is code i ripped from the lecture: http://pastebin.com/2E1UtGdD I put it in pastebin to avoid clutter. Anything used in this is fair game. (this code does have limitiations though, it only support ~9 characters and the looping doesn't work at the end of strings)
I would look at it like this.
Generate a function on paper of how you want to achieve this. This is notes and only a starting point.
Loop from 0 to string length.
if(byte >= 'A' || byte <= 'Z') then byte -= 'A' - 'a'; /* convert to lower case */
if(byte >= 'a' || byte <= 'z') then byte += 'A' - 'a'; /* convert to upper case */
/* Switch the letters only. */
a = 0; b = string length
Loop i from a to b. if((input >= 'A' && input <='Z') || (input >= 'a' && input <='z')) p = i
Loop j from b to a. if((input >= 'A' && input <='Z') || (input >= 'a' && input <='z')) q = j
c = input[i]; input[i] = input[j]; input[j] = c;
/* Regenerate the string and add spaces. */
loop i, 0 to string length
if(input[i] == 'A' 'a' 'E' 'e' ...) string2[j] = ' '; j++; string2[j] = input[i]; j++;
i++
After that if you don't know 8086 I would look at examples online of how to do each individual part. The most important bit is generating the code in your head and on paper on how it is going to work.

converting if else statement to ternary

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.

Resources