In systemverilog, how to detect operand attribute (signed or unsigned) in text macro (define)? - attributes

I am writing a piece of verilog code that negate a value. I expect if operand is signed, return its negative value and it is unsigned, return '1'.
Here is my code,
`define negation (a) ((a<0 || -a<0 || (a-1)<0) ? -a : 1)
Is there any fancy way to detect operand attributes?

There is no built-in attribute to check that an operand is signed. You could write your own attribute
let issigned(v) = (v|~v)<0;
Then use
let negation(a) = issigned(a) ? -a : 1;
You could do this with a text macro, but let is better to catch mistakes.

Related

Why += is considered as an assignment operator while >= is not?

I was thinking why the '=' in '+=' is considered as assignment while '=' in '>=' is not considered as such. There is no importance behind this question but some random thought of a beginner. For example purpose, you can consider that
a = np.array([1,2,3,4,5])
a += 2 # array updated and assigned to a
a>=2 # becomes a boolean indexing filter
a += 2 changes the value of a. It reassigns it's value to be two more than it was before. By the way, += as a whole is the assignment operator, not just the =.
a>=2 does not change the value of a. Yes, it becomes true or false. But 'true' or 'false' is all it is. It does not get assigned to anything. The value of a is as it was before.
You can do b = a>=2. But in that case, = is the assignment operator because it is what assigns the value to b.

== operator in assign statement (Verilog)

I am trying to understand some of the System Verilog syntax. I was struggling to finish an assignment and I came across this solution, but I do not understand why it works.
localparam int lo = w;
uwire [n:0] lo_bits, hi_bits;
assign answer = lo_bits == nlo ? lo_bits + hi_bits : lo_bits;
This is not exactly what I have in my code, but my question is the following: Why can't I rewrite this to a simple if-else block as such?
if (lo == lo_bits)
assign answer = lo_bits + hi_bits;
else
assign answer = lo_bits;
Verilog complains that lo_bits is a uwire and I cannot compare it with lo, but then why is it allowed in the example above? Aren't these two assignments equivalent?
Thank you very much for your help!
The difference is structural/declarative context versus procedural context. When you use an if clause in a declarative context (in this case it is at the same top level where you declare your wires and variables), it is considered a conditional generate construct (See Section 27.5 in the 1800-2017 LRM). This means the condition gets evaluated before simulation starts and must contain only constant expressions and no signals that can change during simulation. lo is a constant parameter, but not lo_bits.
If you want to use a procedural if, it needs to be inside a procedural block of code instantiated by always/initial blocks.
logic [n:0] answer;
always_comb
if (lo == lo_bits)
answer = lo_bits + hi_bits;
else
answer = lo_bits;

Multi-dimentional packed parameter declaration using function

Recently I am thinking pre-calculating all necessary parameters using simple mathematical equations before instantiating logic units in generate struct. In the case where I need to have a 2-D parameter, it's easy if the 2-D array is a set of fixed values, such as
parameter para_1[1:0][2:0] = '{2{3{0}}};.
But what I want is a function that dictates the values, such that complicated equations can be implemented inside the function before assigning the return values to the parameter.
Ideally I want something as follows:
function func01 [1:0][1:0] (input int test);
int index;
for (index=0; index<=2; index++) begin
func01[index] = index + $floor(index/2) + $mod(index, 2) + test;
end
endfunction
parameter test1 = 1;
parameter logic test2 [1:0][1:0] = func01(test1);
But ModelSim complains about the first line of code straightaway - ** Error: (vlog-13069) near "[": syntax error, unexpected '[', expecting ';' or '('.
Ultimately the idea is to have a block that calculates all parameters/constants at elaboration time, so that these can be used in generate block for instantiation, also at elaboration time.
Hope it makes sense, and thanks a lot in advance.
Best,
Taihai
First, if you want packed arrays, the dimension ranges goes to the left of the array name. And I suggest using an explicit data type.
parameter bit [1:0][2:0] para_1 = '{2{3{0}}};.
Then, the return type of function declaration comes before the function name.
function bit [1:0][1:0] func01 (input int test);
BTW if you want the return type of a function to have an unpacked dimension, you must use a typedef, which is a good practice in any case.
typedef bit [1:0] myParam_t [2:0];
parameter myParam_t para_1 = '{default:0};
function myParam_t func01 (input int test);

Verilog bit shift by constant, how is it implemented?

I have a line of code like
parameter [8:0] param1=8'd05, param2 = 8'd20;
A <= cond ? (1 << param1) : (1 << param2);
Will the compiler recognize 1 << param is a constant and replace that expression with a constant or will it try to implement some sort of bit shifter?
Parameters are evaluated at compile time and must be constants.
From IEEE Std 1364-2001:
3.11 Parameters Verilog HDL parameters do not belong to either the variable or the net group. Parameters are not variables, they are
constants.
So it is really up to the Synthesis tool how it will decide to implement a shift by that constant, but any reasonable implementation will simply select the correct wires out of the vector.
In addition, since your examples are constants shifted by a constant, the whole expression reduces to a constant and the code will be equivalent to:
A <= cond ? 32'h20 : 32'h100000;

Verilog Syntax Error

It's verilog code and can't simulate because of syntax error. Anyone know how to solve it?
assign x = (Status == 2'b00)?
{Board[0],1'b0,1'b0,Board[2],1'b0,1'b0,Board[1],1'b0,Board[3],1'b0,1'b0,Board[5],1'b0,1'b0,Board[4],1'b0,1'b0,Board[6],1'b0,1'b0,Board[8],1'b0,1'b0,Board[7],1'b0,Board[9],1'b0,1'b0,Board[11],1'b0,1'b0,Board[10],1'b0,Board[12],1'b0,1'b0,Board[14],1'b0,1'b0,Board[13],1'b0,Board[15],1'b0,1'b0,Board[17],1'b0,1'b0,Board[16],1'b0}:
(Status == 2'b01)?
64'b0110000001100000011000000110000000000000000000000000000000000000:
(Status == 2'b10)?
64'b1101101011011010110110101101101000000000000000000000000000000000:
(Status == 2'b11)?
64'b1001110011101111011100100100000100000000000000000000000000000000:
Form minimum code change:
//(Status == 2'b11)?// <- comment out for final condition
64'b1001110011101111011100100100000100000000000000000000000000000000 ; // <- semicolon, not colon
Better yet convert to a case statement. Easier to read and debug.
reg [63:0] x;
always #* begin
case(Status)
2'b00: x = ... ;
2'b01: x = ... ;
2'b10: x = ... ;
2'b11: x = ... ;
endcase
end
x= (condition==2'b00)? a:(condition==2'b01)?:b:(condtion==2'b10)?:c:(condtion==2'b11)?:d
This is how your code looks when the values for assigning to x are replaced with a,b,c,d.The statement will definitely throw an error as you have clearly violated the way ternary operator is supposed to be used.
Ternary operator syntax:
x=(condition)?a:b
If the condition is true, x will be assigned the value of a.
If the condition is false, x will be assigned the value of b.
Ternary operator syntax if used in a nested way:
x=(condition1)?a:((condition2)?b:c)
If the condition1 is true, x will be assigned the value of a.
If the condition1 is false, it will check for condition2. If condition2 is true, x will be assigned the value of b else x will be assigned the value of c.
Looking at your code, you have repeated colons at inappropriate places.
x= (condition==2'b00)? a:(condition==2'b01)?:b:(condition==2'b10)?:c:(condition==2'b11)?:d
^ ^
There should not be a colon after the question mark.
Probably you can rewrite the condition as:
assign x= (condition==2'b00)?a:(condition==2'b01)? b:(condition==2'b10)?c:d;
Look at the small verilog code that helps in understanding the working of nested ternary operator:
Verilog code
Hope my code helps you!
You havent posted any specific error message.
A good way of Debugging :
Use $Display("any text") near line numbers that are pointed out as errors in the code by the compiler. From the code it seems you are doing a lot of Vector part Select. Case statement is a better choice.

Resources