- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have the following code:
input signed b;
input signed c;
input signed d;
output signed e;
wire signed f;
assign f = b*c/d;
assign e = f
I believe that Quartus is eliminating f and replacing my two assignments with: assign e = b*c/d;
which causes b*c to overflow and the operation is effectively e = ((b*c)%2^14)/d. The purpose of f is to expand b and c so that no overflow occurs. After dividing by d the result cannot be larger than 2^14. If I make f an output rather than just a wire, Quartus does not eliminate it and the operation is performed correctly. Is there some way to get Quartus to not eliminate f without making f an output?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- If I make f an output rather than just a wire, Quartus does not eliminate it and the operation is performed correctly. Is there some way to get Quartus to not eliminate f without making f an output? --- Quote End --- When you say you made f an output and got the correct result, do you mean that you only made the lower 14 bits f[13:0] the output or the output was the full 'f'? Picking off only the lower bits for output would be equivalent, outputting the full f would not. Kevin Jennings
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I outputted the full f.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you give a numerical example what you get versus what you expect?
--- Quote Start --- After dividing by d the result cannot be larger than 2^14. --- Quote End --- Why? Generally it's 28 bit long.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, I should have provided more information. Because of other logic, d cannot be less than c. Hence, b*c/d cannot be greater than b. To show why d cannot be less than c, here is the rest of the logic:
input signed b;
input signed c0;
input signed c1;
output signed e0;
output signed e1;
wire signed f0;
wire signed f1;
wire d2;
wire d;
assign d2 = c0*c0 + c1*c1;
sqrt u1 (.radical(d2), .q(d)); // d = d2^0.5
assign f0 = b*c0/d;
assign f1 = b*c1/d;
assign e0 = f0;
assign e1 = f1;
d is the magnitude of (c0, c1) so neither c0 nor c1 can be greater than d. e0 and e1 are exactly what I expect when I make f0 and f1 outputs. That is, wire signed f0;
wire signed f1;
is replaced with output signed f0;
output signed f1;
However, when f0 and f1 are not outputs, instead of f = b*c/d, I get f = ((b*c)%(2^14))/d, where % stands for modulus. For example, when b = 2000, c0 = 1536, and c1 = 640, I expect e0 = 1846 and e1 = 769. I get this when f is an output, but when it is not I get e0 = 1 and e0 = 4. What I think is happening is Quartus is simplifying assign f0 = b*c0/d;
assign f1 = b*c1/d;
assign e0 = f0;
assign e1 = f1;
into assign e0 = b*c0/d;
assign e1 = b*c1/d;
In the first case, since f is 28 bits long, the right hand side should be expanded, which prevents b*c from overflowing and gives the correct result. In the second case, all of the signals are 14 bits long, so b*c overflows before it is divided by d. What I want to know is whether there is a way to get Quartus to not eliminate the signal f without making f an output.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not that I'm following this well but in your original post you said that it appears that 'f' is being optimized away. I would expect this to happen if you don't use it anyway but the assignment into 'e'.
I recommend sticking to your code fragment at the start of your post and tell us what you were using for inputs b, c, and d and we can then tell you exactly how the logic should behave. Were any of the inputs hardcoded by any chance?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't understand why it matters what I am using for inputs b, c, d. b is a constant 2000. I think this is what you mean by hard-coded. c is not hard-coded. It is a random value that changes on every clock cycle. d is not actually an input as you can see if you look at my third post. I made it an input in my first post because I didn't think it mattered where it came from and I wanted to post a simplified version of the code. sqrt is a square root module, d2 is its input, and d is it's output. d = (c0*c0 + c1*c1)^0.5
I think I understand how the logic is behaving. What I really want to know is whether there is some way of preventing the overflow other than having extra outputs that are never used. I found the rules for when signals are expanded and I found out that all of the signals are expanded to be the size of the longest signal in an assignment. This is what led me to use f as an intermediate signal in calculating e. This doesn't help, however, if Quartus just ignores the signal. I could instead make e longer but I don't want another module to have to know to ignore the top 14 bits of one of its inputs. I'm wondering if there is some standard way of ensuring that overflows do not occur in the intermediate steps of calculations.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When inputs are hardcoded some additional optimizations may occur which is why I was asking. Typically when I need to worry about this sort of thing I carry out the operations as sequential assignments. So something like this:
input signed [13:0] b; input signed [13:0] c; input signed [13:0] d; output signed [13:0] e; wire signed [27:0] g; wire signed [27:0] f; assign g = b * c; assign f = g / d; assign e = f[13:0]; Have you tried doing the same and if so does the same behavior occur? Also to prevent optimizations from happening you can use the (* keep *) keyword. So when you declare 'f' you would do it like this: (* keep *) wire signed [27:0] f;- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for providing the details.
I reviewed IEEE Std 1364 chapter 5.4.1 rules for expression bit lengths and don't see an unequivocal rule for the said case assign f0 = b*c0/d; It's clear, that in the solution suggested BadOmen assign g = b * c; no overflow occurs, but in your original example, the assignment LHS possibly doesn't rule the bit width of the multiply, instead the width of the factors (14 bit) will be assigned. Thus making an explicite width assignment seems appropriate. Alternatively you can extend one factor by a concatenation with a zero bit vector 14'b0.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried something very similar to what BadOmen suggested and it worked:
input signed b;
input signed c;
input signed d;
output signed e;
wire signed g;
assign g = b * c;
assign e = g / d;
Thank you for telling me about the keep keyword. That will be very useful. FvM, I think you mean chapter 4.4.1. Thank you for your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Good that it works.
Chapter 4 expressions in IEEE Std 1364 2001 became Chapter 5 in the 2005 release.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You didn't need to use the keep keyword for this to work right? (I wouldn't expect you to really need it if you break the calcuation down into two assign statements with the appropriate widths).
I recommend not getting into a habit of using the keep keyword since it prevents having Quartus II optimizing that net when it or portions of it are not used in your design. I normally only use it for debug purposes.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, I didn't need to use the keep keyword. I just thought I might use it in the future to make certain signals available for observation in a simulation.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page