SystemVerilog case statement does not work - system-verilog

Anyone know why this case statement doesn't work:
int width;
width = 8;
case (width === 16)
1'b0: begin
// correct code
end
1'b1: begin
// we end up here
end
endcase
I am using VCS. I tried running this with DVE debugger, and the code worked correctly when running with the debugger. Also, this code is nested within another case statement, not shown here.

I can't directly answer you question, but I think synopsys will not make that stupid mistake. If they did, please let me know.
In some language, the return value '0' means true, I am not sure it is the same here.
But to avoid this issue, I think the code can be changed to other ways:
One way:
case (width)
16 : begin
// correct code
end
default : begin
// Other code
end
endcase
Or:
if (width === 16) begin
// correct code
end

Related

How to prevent new threads of SVA

Lets assume, I have a button in my design. I want to increment counter between next two clock when button has been pressed three times and I want to check this behaviour with SVA.
I have wrote this one:
`timescale 1ns / 1ps
module tb();
parameter NUMBER_OF_PRESSES = 10;
parameter CLK_SEMI_PERIOD = 5;
bit clk;
always #CLK_SEMI_PERIOD clk = ~clk;
bit button_n;
bit reset_n;
logic [7:0] counter;
property p;
logic[7:0] val;
disable iff(!reset_n) #(posedge clk) (($fell(button_n)[=3]),val=counter) |=> ##[0:2] (counter== val+1);
endproperty
assert property(p);
initial begin
automatic bit key_d;
automatic byte key_lat;
automatic byte key_press_count;
reset_n = 1;
button_n = 1;
counter = 0;
fork
begin
repeat(NUMBER_OF_PRESSES) begin
repeat(5)begin
#(negedge clk);
end
button_n = 0;
key_lat = $urandom_range(1,4);
repeat(key_lat) begin
#(negedge clk);
end
button_n = 1;
end
end
begin
forever begin
#(posedge clk);
if(!button_n && key_d) begin
key_press_count++;
end
if(key_press_count == 3) begin
counter++;
key_press_count = 0;
end
key_d = button_n;
end
end
join_any
end
endmodule
This works good at first three press, but then it will always throw assertion error, because it has been started new thread of assertion at each button press. So, I need to prevent testbench from doing this. When repetitition has been started I don't need to start new threads.
How can I do this?
I am not confident I fully understand your question. Let me first state my understanding and where I think your problem is. Apologise if I am mistaken.
You intend to detect negedges on button_n ("presses"), and on the third one, you increment "counter".
The problem here is that your stated objective (which actually matches the SVA) and your design do different things.
Your SVA will check that the counter has the expected value 1-3 cycles after every third negedge. This holds for press 0, 1 and 2. But it must also hold for press 1, 2 and 3. And press 2, 3 and 4 etc. I suspect the assertion passes on press 2 and then fails on press 3. I.e. you check that you increment your counter on every press after the third.
Your design, on the other hand does something different. It counts 3 negedges, increments counter, and it then starts counting from scratch.
I would advise against the use of local variables in assertions unless you are certain that it is what you need - I don't think this is the case here. You can have your SVA trigger on key_press_count == 3 (assuming you ofc define key_press_count appropriately and not as an automatic var).
If you insist on using your local SVA variable you can slightly modify your trigger condition to include counter. For example something along the lines of (though may be slightly wrong, have not tested):
(counter == 0 || $changed(counter)) ##1 ($fell(button_n)[=3], val = counter)
IMO that's a bad idea and having supporting RTL is the better way to go here to document your intention as well as check exactly the behaviour you are after.
Hope this helps

SystemVerilog/Verilator WIDTH parameter and case structure indexing out of bounds

I'm currently implementing a PRNG in SystemVerilog using an LFSR as described here. The width should be variable using a parameter. I reach a construct of:
module PRNG
#(
parameter WIDTH = 32,
parameter SEED = 1
)
(
input clk,
input update,
output reg [WIDTH-1:0] prng
);
reg [WIDTH-1:0] lastRng = WIDTH'(SEED);
always_comb begin
var tap;
case (WIDTH)
default: tap = 0;
3: tap = lastRng[2] ^~ lastRng[1];
[...]
168: tap = lastRng[167] ^~ lastRng[165] ^~ lastRng[152] ^~ lastRng[150];
endcase
if (update) begin
prng = {lastRng[WIDTH-2:0], tap};
end else begin
prng = lastRng;
end
end
always_ff #(posedge clk) begin
lastRng <= prng;
end
endmodule
Now, while simulating this module using Verilator it complains of selection indices out of range for every case > WIDTH-1, even though (I think that) these cases should clearly be optimized out, since WIDTH is a constant:
Selection index out of range: 167:167 outside 31:0
Is there a simple way around this error, without eg. bit shifting logic just to index the nth bit?
To do this, you need to use a generate.
Try this
Move the case statement block outside of the always_comb (you can't use generate in an always block, someone correct me if that does not stand for always_comb
Change the tap = statements to be assign tap =.
(optional) Surround the case block with generate/endgenerate. This isn't required but you might find it helps readability.
You need to restructure your block so you don't have out-of-bound references. In simulation, the compiler is not required to optimize your procedural code based on constant values, so it needs to be legal. Moving the case statement outside the always block changes it from procedural to elaboration based (same for if and for-loop statements.
logic tap;// same as var tap, but better to show the implicit data type
case (WIDTH)
default: assign tap = 0;
3: assign tap = lastRng[2] ^~ lastRng[1];
[...]
168: assign tap = lastRng[167] ^~ lastRng[165] ^~ lastRng[152] ^~ lastRng[150];
endcase
always_comb
if (update)
prng = {lastRng[WIDTH-2:0], tap};
else
prng = lastRng;

How to return boolean in if else statement and the return value will link to anothe if else statement in Matlab?

I have the following if else statement that created by myself in order to link to the if else statement given in second part:
m=4
if m==3
disp(true)
else
disp(false)
Second part ( this code is fix cannot be change):
if (true)
A=Hello World
else
A=Bye
If using the first part code, my output will be
A=Hello World
but my desire output is
A=Bye
Anyone one have idea to edit the first part, because now my return value in first part not able to link to my second part.
If you can't change the second part's code, I'm afraid your desire cannot be fulfilled. Or rather, I'm afraid your code won't run at all, because your perenthesis, quotes, end-statement (and arguably semicolons) are not in place.
if true
A = 'Hello World';
else
A = 'Bye';
end
This code will return A = 'Hello World', no matter what, since true is always true. If-else conditions work like this:
if (*what's in here evealuates to true*)
%do stuff
else (*if what's up there does not evaluate to true*)
%do other stuff
Clearly, true will always evaluate to true. So the above if-else condition will always return A = 'Hello World'.
You don't need two if statements in order to accomplish this task. One is more than enough to perform all what you need:
m = 4;
if (m == 3)
A = 'Hello World';
else
A = 'Bye';
end
disp(A);
A few comments concerning your code:
if statements need to be closed with an end
if (true) will always pass into the statement
the disp function doesn't assign a value, its only goal is to display it in the Command Window
in order to work with text, you have to enclose it within single quotes ' (char array) or double quotes " (string), more info here
If you posted only small excerpts of your code and you need to perform those two checks sequentially, in different parts of your script, then:
m = 4;
if (m == 3)
m_equals_3 = true;
disp('M == 3');
else
m_equals_3 = false;
disp('M ~= 3');
end
% then, somewhere else...
if (m_equals_3)
A = 'Hello World';
else
A = 'Bye';
end
% ...
I guess this is a homework exercise. You should disclose that if it’s the case.
The exercise requieres you to change the workspace such that the second bit of code evaluated the else case. This can be accomplished by changing the meaning of true. In your first bit of code, make it so that
true = flase;
Or equivalently,
true = 0;
Note that this is really bad form, if you ever do something like this outside of a homework exercise that explicitly asks you to do so, you’ll get fired or maybe even shot. You’ve been warned!
By the way, I assume that the missing quote characters around the strings and the missing ends are typos?

Constraint gives a warning on ranges are not relevant

the following code creates a warning on DEPR_NEG_OR_LARGE_SELECT_WEIGHT:
keep soft MyVar == select {
0xffffffffff: 0;
10: [1..10];
10: [11..20];
};
keep MyVar != 0;
i would expect the check to consider only the relevant ranges...
0xffffffffff is not a legal syntax of a select weight. Only values between 0 and MAX_INT are valid.
The tool simply protects you from illegal expressions. Just as you get a load/compile time error if you write any other illegal code. It doesn't try to understand the deeper meaning, or whether the code is at all called.
This should be enough for your needs.
keep soft MyVar == select {
1: [1..10];
1: [11..20];
};
keep MyVar != 0;
keep soft MyVar in [1..20]; // This is also enough in place of weighted random constraint.

use debugger in matlab

i want to debug following simplest code in matlab and clarify why it executes always if statement
function testfile(x)
if 3<x<6
disp('in the middle of range');
else
disp('out of range');
end
end
i have used following code for debugger
echo testfile on
testfile(-2)
in the middle of range
testfile(6)
in the middle of range
why it does not execute else statement?i have used following code as a test
5<4<8
ans =
1
so does it mean that writing if statement in this style is wrong?a i understood it is same as if 5<4 || 4<8?then it makes clear for me why it executes only if statement and never reaches to else
5<4<8 is evaluated as (5<4)<8. If we resolve the expression in the parentheses first, we have 0<8, which is true. Test with 5<4==0, which evaluates to true.
What you want to do is check whether x is both bigger than 3 and smaller than 6, i.e.
3<x && x<6