From: rickman on 15 Mar 2010 16:10 I am converting an integer equation to use numeric_std data types and it looks rather awkward. Here is the equation... PhaseStep <= (IntgrPhase + (PROPGAIN * DataCount) + FreqStep) mod MODULUS; The names in caps are integer constants, PhaseStep and FreqStep are unsigned while IntgrPhase and DataCount are signed, all four the same length, 16 bits. The true range of DataCount will be very limited so it is invalid that it will cause an overflow of the result. In fact, it is considered an operational error if any of this causes an overflow in the result... that is the inputs must have been out of whack, not the circuit. So I'm not worried about the math at that level. I'm concerned about how to get the circuit I want without a lot of difficult typing of syntax. I just want this stuff to be added to produce a 16 bit result. When doing this using integer arithmetic it all works well. In simulation it only barfs if a value exceeds its range and the synthesis result uses the correct number of bits in the implementation. I don't see it using any extra bits in the calculations which makes sense, why calculate bits you aren't using in the end? To add the signed and unsigned values, I believe I will have to add a bit to the unsigned FreqStep before adding to the signed values. The significant bits will not flow into the added bit, so it can be dropped in the end. But this will complicate the result a lot. PhaseStep <= resize(unsigned(IntgrPhase + (PROPGAIN * DataCount) + signed(resize(FreqStep,STEPWIDTH+1)) mod MODULUS), STEPWIDTH); Am I making this more complicated than it needs to be? If I just convert FreqStep to signed without the resize, it will treat the msb as a sign bit and corrupt the value, right? I guess the fact that I call it a signed value doesn't change the circuit, but it will change the simulation, right? The other thing I could do is to convert them all to integer and then back, but that is no less messy. Any ideas on a way to make this expression simpler? Rick
From: glen herrmannsfeldt on 15 Mar 2010 16:45 In comp.arch.fpga rickman <gnuarm(a)gmail.com> wrote: > I am converting an integer equation to use numeric_std data types and > it looks rather awkward. Here is the equation... > PhaseStep <= (IntgrPhase + (PROPGAIN * DataCount) + FreqStep) mod > MODULUS; > The names in caps are integer constants, PhaseStep and FreqStep are > unsigned while IntgrPhase and DataCount are signed, all four the same > length, 16 bits. The true range of DataCount will be very limited so > it is invalid that it will cause an overflow of the result. How big can the values be? The result can't overflow because of the MOD. (It can't exceed MODULUS-1), but multiplying two 16 bit integers can reach 32 or so (signed or unsigned?) bits. > In fact, > it is considered an operational error if any of this causes an > overflow in the result... that is the inputs must have been out of > whack, not the circuit. So I'm not worried about the math at that > level. I'm concerned about how to get the circuit I want without a > lot of difficult typing of syntax. If DataCount can't get so big, then a lookup table based on the constant PROPGAIN would be easy and fast. That is, do: PhaseStep <= (IntgrPhase + ((PROPGAIN * DataCount)mod MODULUS) + FreqStep) mod MODULUS; Then, depending on the size of IntgrPhase and FreqStep, another table or some simple adder logic could do the second modulus. It is somewhat easier if MODULUS is a power of two, but you can still do it even if it isn't. Another possibility so to multiply DataCount by an appropriately scaled PROPGAIN such that a power of two modulus can be used, then multply the result to get the correct MODULUS. You have to be careful with rounding, but I believe that can be done. Doing division by multiplication with an appropriately scaled reciprocal is common, and the rounding is well understood. It isn't quite as obvious for mod, but I believe it can still be done. (The latter assumes you have hardware multipliers available, as many current FPGAs have.) -- glen
From: Andy on 15 Mar 2010 18:12 This may be a silly question, but why do you need to convert it to signed/unsigned? If it works in integer, leave it be... The simulation will be much faster, and the circuit just as good. Glen sounds like he's got some good implementation ideas, but if you're primarily interested in expressing the problem in a simple readable way, integer types are the clear winner. This is one of those golden examples of why I like integers so much! Or do you want it to be scalable to > 31 bits? That would be an example of why I want integer to be bigger! Andy
From: rickman on 15 Mar 2010 19:08 On Mar 15, 6:12 pm, Andy <jonesa...(a)comcast.net> wrote: > This may be a silly question, but why do you need to convert it to > signed/unsigned? If it works in integer, leave it be... The simulation > will be much faster, and the circuit just as good. Glen sounds like > he's got some good implementation ideas, but if you're primarily > interested in expressing the problem in a simple readable way, integer > types are the clear winner. This is one of those golden examples of > why I like integers so much! > > Or do you want it to be scalable to > 31 bits? That would be an > example of why I want integer to be bigger! > > Andy Thanks for the reply. No, I don't need > 31 bits. I just am using this in a case where all the connecting signals are signed/unsigned rather than integer. The various parameters are just shifting factors rather than arbitrary scale factors. In the integer approach I used a multiplication while a shift might be more appropriate with a vector although I think the impact is more clear using the multiply. After all, it is implementing a formula... The issue is not if my math is good. The only question I have is whether there is a better way to express it in VHDL. BTW, I think I need parens around the stuff the mod is acting on, if nothing else a bit more clarity... Rick
From: Andy on 16 Mar 2010 09:04 Though it won't help with signed/unsigned issues, you may also want to look at the fixed point package. It automatically promotes result sizes to maintain accuracy for multiplication, addision and subtraction. You can use it for "integer" math by simply specifying your LSB index at 0. The idea is that intermediate result or operand resizing is not usually needed with fixed point, just a final resize prior to storage (like the implied resize that happens with integers). I really wish they had gone the extra step to make ufixed - ufixed = sfixed, but alas, that did not happen (not that it would be an issue in your problem). With that, we'd have 99% of the flexibility of integers (automatic signed and size promotion), with virtually unlimited data sizes, at reduced simulation performance (compared to integer, not signed/unsigned). Andy
|
Next
|
Last
Pages: 1 2 Prev: how to use the design results of the vhdl code for a program inC code Next: VHDL-2008 'protect |