Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c=1?$signed(a)>>>1:a>>1 appears miscompiled #208

Closed
tommythorn opened this issue Sep 23, 2018 · 3 comments
Closed

c=1?$signed(a)>>>1:a>>1 appears miscompiled #208

tommythorn opened this issue Sep 23, 2018 · 3 comments

Comments

@tommythorn
Copy link

This is a dramatically reduced test case (the original looks nothing like this).

module t;
reg z=1;always#5z=!z;reg[31:0]a=0,b=0,c,d;
always@(*)begin
  c=1?$signed(a)>>>1:a>>1;
  d=$signed(a)>>>1;
end
always@(posedge z)begin{b,a}<={b,a}+'h1000;if(d!=c)$display("F");end
endmodule

In my understanding this should never print anything, but it does for me.

I'll try to rebuild from git, but Mac Brew is up to date.

@tommythorn
Copy link
Author

iverilog bug.v && ./a.out | head
F
F
F
...

@martinwhitaker
Copy link
Collaborator

Icarus is behaving correctly here. The right hand side of your assignment to c is an unsigned expression (the true branch is signed but the false branch is unsigned, so the overall expression is unsigned). The Verilog >>> operator only performs an arithmetic shift if the result type is signed (that's daft, but it's what the IEEE standard says).

To get the behaviour you expect, you need to write

  c=1?$signed(a)>>>1:$signed(a)>>1;

@tommythorn
Copy link
Author

Wow, thanks. That is insane; what we’re they thinking. I’ll fix my code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants