Author Topic: FPGA: PID controller (VHDL newbie)  (Read 6452 times)

0 Members and 1 Guest are viewing this topic.

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
FPGA: PID controller (VHDL newbie)
« on: April 17, 2020, 10:50:48 pm »
Hello, it's me again with my FPGA adventures, learning VHDL by practicing it.

Today I have tried to implement a PSD controller (just PS to be specific). Being bit more knowledgeable I have gone straight to the incremental form to spare myself the pain experienced by many others. PS controller difference equation should be:

y(n) = y(n-1) + A0*x(n) + A1*x(n-1)

where the transformed coefficients shall be

A0 = Kp + Ki
A1 = Kp


I have tried to implement it using just my own ideas cobbling together some state machine, that should go through the equation step by step. But that failed miserably, making the horrendous mess you can see attached. Very resource hungry and very ineffective. After seeing what my original code has synthesized to, I have realized it would be better to start from scratch and think a bit more before writing some code, rather than doing it the other way round.

After bit of paper + pencil + brain time, I came up with this circuit idea below.  The idea is to have a 16bit precision input/output controller, with an internal 32bit accumulator.  Following the equation mentioned above, it seems to me, the whole PS controller can be calculated in just two multiply-accumulate steps, using the same 32bit adder and the same 16x16 multiply, just by multiplexing the inputs to the multiplier.

That way I think I can get the best resource usage and a sensible implementation that will probably also work. Also, it would be handy to add intermediate registers around the multiplier to speed stuff up, but those were omitted for clarity (and I do not need that much speed anyway).

972158-0

The register on the left side is the z-1 representing the x(n-1) term.

The whole then shall be controlled by a simple state machine: Either idle (waiting to trigger the calculation), or then in the two states of calculating the two products of A0*x(n) and A1*x(n-1).

The question is, is this a sensible approach or not and why?

I have tried at first to find a suitable beginner tutorial, but I only mostly find it implemented in the most ugly way that could compete with my original one.

//EDIT: Ugly typos.
« Last Edit: April 17, 2020, 11:24:28 pm by Yansi »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2812
  • Country: nz
Re: FPGA: PID controller (VHDL newbie)
« Reply #1 on: April 18, 2020, 12:29:40 am »
I think you might be better off using two multipliers, as that way you can use different 'scale factors' for the A0 and A1 constants, and on their products. It also avoids the need for MUXs and an FSM.

You can also run at half the clock rate for the same throughput...

In most FPGAs the DSP blocks are set up for cascading of operands and products, which could be leveraged if highest performance is needed.

Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 8024
  • Country: ca
Re: FPGA: PID controller (VHDL newbie)
« Reply #2 on: April 18, 2020, 01:18:45 am »
VHDL :(

(It just means I really wanted to help, but I only know System Verilog)
« Last Edit: April 18, 2020, 07:26:52 am by BrianHG »
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #3 on: April 18, 2020, 10:08:30 am »
VHDL :(

(It just means I really wanted to help, but I only know System Verilog)

Well I did not ask for code... yet!  ;D So it's fine, just asking about the generic principles, I can probably then cobble some code together and make another useless logic mess.   ^-^

I think you might be better off using two multipliers, as that way you can use different 'scale factors' for the A0 and A1 constants, and on their products. It also avoids the need for MUXs and an FSM.

You can also run at half the clock rate for the same throughput...

In most FPGAs the DSP blocks are set up for cascading of operands and products, which could be leveraged if highest performance is needed.

I have the smallest Cyclone IV FPGA of them all and am afraid I would run out of resources, if I'd be using too much logic hungry design.  hence my question if it is sensible to optimize like this. Different scale factors for A0 and A1 are rarely required - at least from my experience working with SW on a different platform.  The scale is applied by scaling the input/output of the controller function.

So considering the same scale factor and resource usage constraint, does the above make sense? Little FSM to control it will probably not add much logic. (At least thats what I think now)
 

Offline OwO

  • Super Contributor
  • ***
  • Posts: 1250
  • Country: cn
  • RF Engineer.
Re: FPGA: PID controller (VHDL newbie)
« Reply #4 on: April 18, 2020, 10:24:04 am »
Yes, your general approach is sound: drawing a diagram before writing code, utilizing basic building blocks (mux, flipflop, arithmetic units, etc), and understanding how they map to FPGA resources.

I haven't seen your code so I can't comment on that, but I do recommend putting enough detail into your diagrams so that the code is basically a mirror image of the diagram. For example, if there are pipeline registers, it changes the logic and overall timing, so it's best to leave those on the diagram.
EDIT: I also recommend drawing timing diagrams to clarify the operation of the circuit and so you have something to check against when troubleshooting simulations or logic analyzer waveforms.

Wouldn't it be possible to omit mux2? Since when it comes time to calculate A1*x(n) the input has already moved to the next value; if you need to handle non-continuous data you could add a clock enable term to all flipflops but this comes at a performance penalty. mux1 can also be omitted by using a shift register ring, but the mux approach is also cheap because the inputs are constant.
« Last Edit: April 18, 2020, 10:33:08 am by OwO »
Email: OwOwOwOwO123@outlook.com
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #5 on: April 18, 2020, 12:02:30 pm »
Hello, it's me again with my FPGA adventures, learning VHDL by practicing it.

Today I have tried to implement a PSD controller (just PS to be specific). Being bit more knowledgeable I have gone straight to the incremental form to spare myself the pain experienced by many others. PS controller difference equation should be:

y(n) = y(n-1) + A0*x(n) + A1*x(n-1)

where the transformed coefficients shall be

A0 = Kp + Ki
A1 = Kp


That way I think I can get the best resource usage and a sensible implementation that will probably also work. Also, it would be handy to add intermediate registers around the multiplier to speed stuff up, but those were omitted for clarity (and I do not need that much speed anyway).
IMHO you are making the classic mistake to think in terms of logic. Also in many cases you won't need the D part from PID so let's just look at the PI part.

In VHDL you can write this (with all signals defined as integer types):

error <= setpoint - input;
integrator <= integrator + error * ki;
output <= integrator + kp * error;

and the synthesizer will map it onto FPGA logic (whether it has built-in multipliers / adders) or not. If you have a specific FPGA as a target then make sure to read the synthesizer manual on how calculations are mapped on hardware. It is possible that you can get a better resource usage by writing the equations in a certain way. You can probably add the D part yourself.

Now onto the interesting part of implementing a PID controller using fixed point math; you'll have to very carefully think about having enough resolution and catching overflow conditions. You'll likely want to limit the range of the integrator so it doesn't wrap around (remember the integrator's main purpose is to take care of DC offset in the control loop). A good idea is to create a test bench and simulate your PID controller to see if you have enough resolution. I think 16 bits may not be enough so if the building blocks only support 16 bit then you'll need to cascade them; let the synthesizer handle that for you. Another interesting excersize is to write the equations in various ways and see how that affects the implementation (speed and resource wise). That knowledge can be universally applied to future projects instead of going the tedious hand crafting route every time.

Now someone will probably chime in and say that writing equations is never going to get the best performance yadda yadda yadda yadda. But you can't go around hand-optimising large FPGA designs. It is like writing an entire microcontroller application in assembler instead of C. VHDL synthesizers are much more capable than people seem to think. You can achieve the resource sharing through the synthesizer as well if you rewrite the PID controller as a statemachine. But read the synthesizer manual on how to achieve that.
« Last Edit: April 18, 2020, 12:18:26 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #6 on: April 18, 2020, 12:30:54 pm »
Whats wrong about thinking in terms of logic, if designing a logic circuit is exactly what I am doing?

Your suggestion of

Quote
error <= setpoint - input;
integrator <= integrator + error * ki;
output <= integrator + kp * error;

is exactly what leads to a mess*.   Please read carefully, as I have said clearly, the derivative (Kd) is not used and I am also using the proper DSP-friendly form of a PS controller in the incremental form, where you do not need to care about some overflowing sum.

There is nothing that can overflow in the PS controller equation in incremental form, if all one does is to just use a saturated addition for the accumulator. Saturated add function is easy to implement, using just some combinatorial logic from the upper bits and a MUX, that swaps output for a  maximum positive / minimum negative value. I got that already working, see below:



* Likely requiring one more 32bit register for the integrator and  uses 2 multipliers instead of one. And also one more 32bit adder.  That is already way too many more resources used.
« Last Edit: April 18, 2020, 12:46:46 pm by Yansi »
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3306
  • Country: gb
Re: FPGA: PID controller (VHDL newbie)
« Reply #7 on: April 18, 2020, 12:43:10 pm »
Whats wrong about thinking in terms of logic, if designing a logic circuit is exactly what I am doing?

Your suggestion of

Quote
error <= setpoint - input;
integrator <= integrator + error * ki;
output <= integrator + kp * error;

is exactly what leads to a mess*.   Please read carefully, as I have said clearly, the derivative (Kp) is not used


Kp has nothing to do with the derivative, it's the gain for the proportional term.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #8 on: April 18, 2020, 12:46:31 pm »
Kd, of course. That is a typo there.

//corrected, thanks for pointing that out.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #9 on: April 18, 2020, 01:09:31 pm »
Whats wrong about thinking in terms of logic, if designing a logic circuit is exactly what I am doing?

It is local optimalisation. Local optimisation is a slow process which in the end is limited by how efficient a certain approach can be implemented. It is better to start with a more efficient method at a higher level.  Just read the synthesizer manual to see how you can infer resource sharing and go from there to look for a PI loop implementation which fits best on that. Also, don't look at the intermediate output from the synthesizer but at what is actually going into the FPGA. The synthesizer may produce a lot of extra logic so the solution may seem sub-optimal but all unused logic will be optimised away at a later stage.
« Last Edit: April 18, 2020, 01:26:51 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #10 on: April 18, 2020, 01:23:56 pm »
But I do not understand how does writing "a mess" at first help me to reach more optimal (in terms of resources used) solution?

I have no doubts that the synthesizer can do some clever tricks and what not, but I think the code you have suggested will not or could not ever optimize to something like I have drawn on the paper, which to me seems like a pretty good solution to not waste resources.

Or am I missing something there?

(I will now try to put down some code to try sythesize my circuit from the paper drawing.)
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #11 on: April 18, 2020, 01:27:45 pm »
You have to start somewhere and that is the synthesizer manual and see what they write in there about resource sharing. From there re-write equations to steer the synthesizer towards an optimal solution.

I'm also not sure whether your DSP friendly solution is the best option. Usually there is a factor of 100 to 1000 between Kp and Ki. Combining them into one multiplication factor seems like a sure way to loose resolution. Having a seperate integrator (which can be bit-shifted for free) looks like a better plan to me in order to reduce the number of bits needed while keeping resolution high. If you want to share the multiplier you can calculate the integrator (a 32 bit register) in the first cycle and then add the top 16 bits from the integrator with the multiplication of kp * error in the second cycle. In the end the amount of logic you need is the same. But this kind of optimisation really starts by determining the minimum number of bits you need to achieve the required accuracy.
« Last Edit: April 18, 2020, 01:42:00 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #12 on: April 18, 2020, 01:43:46 pm »
I come from the motor control / power electronics world and I admit I have never stumbled upon a place I would need separate scales for those two. But being rather young there may be a lot to see yet, no doubts.  We have always scaled just the whole input/output of the controller.

Sure, 16 bits fixed-point PI controller is not much resolution. 100 : 1 scale is just 7 bits difference, leaving still 7 bits of precision. Also, no precision is lost, as the accumulator is not truncated and full multiplication accuracy is kept there.

I will probably modify it for 32 bits later, but I need something simple that works first.  Using a 32x32 multiply would eat 4 of the 18bit multipliers per single operation.  Using your approach of "mess code first", I would need  2 of those 32x32 multipliers per controller, meaning 8 HW multipliers per controller. The FPGA only has 15 of them and I need 6 controllers total. That does not fit well, hence it got me thinking about improving my approach to begin with.

Sure I can make a 4-stage pipelined multiply to use just a single 16bit multiplier to do a full 32x32 multiply in 4 steps. But that is too much trouble for a VHDL beginner. Even though I know some tricks how to improve things, I have a lot of troubles fighting with VHDL syntax, types and what not now, so trying to do simple steps first.

What you have suggested was essentially what I have started with, now trying to improve it.

 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #13 on: April 18, 2020, 02:03:21 pm »
You need a maximum of 2 multipliers per PI controller if you keep the data paths at 18 bit. So 6 controllers would need 12 HW multipliers. I'm not too familier with the Cyclone FPGAs but I assume each HW multiplier has an accumulator as well. That accumulator would be very useful as an integrator.

So something like this with all signals as 18 bit signed numbers except for the integrator (which I assume would have at least 36 bits):

error <= input - setpoint;
integrator <= integrator + ki * error;
mul_add <= error * kp + integrator(35 downto 18);
output <= mul_add(35 downto 18);

This should synthesize into using 2 HW multipliers per PI controller. The value for ki is divided by 262144 for free.

You can play with speed versus amount of logic by placing the lines 'error <= input - setpoint;' and / or 'output <= mul_add(35 downto 18);' outside a clocked process.
« Last Edit: April 18, 2020, 02:05:09 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline OwO

  • Super Contributor
  • ***
  • Posts: 1250
  • Country: cn
  • RF Engineer.
Re: FPGA: PID controller (VHDL newbie)
« Reply #14 on: April 18, 2020, 02:14:49 pm »
Number of multipliers you would use is entirely set by the maximum sample rate you need to handle. If this is something like 1Msps, use a single 18x18 multiplier and multiplex it, and you can get away with writing behavioral code because the whole thing would only need to run at 48MHz for 6 channels. The dataflow methodology and heavy pipelining is what I do to hit 350MHz on the slowest speed grade Artix.
Email: OwOwOwOwO123@outlook.com
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #15 on: April 18, 2020, 02:19:19 pm »
32x32 multiply (or 36x36) requires  four 16x16 (or 18x18) HW multipliers.

No accumulators after the multiplier.  Just optional registers on both inputs or the output.  Cyclone IV is quite simple FPGA I guess.  Already investigated in the device handbook.

OwO: I need to run all controllers at like 10kHz rate or what, so I could happily multiplex just one to do all the work. A bit funny to use FPGA for this, but there's other HW I need that I can't get or emulate using a generic MCU.
« Last Edit: April 18, 2020, 02:22:03 pm by Yansi »
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #16 on: April 18, 2020, 02:20:56 pm »
Number of multipliers you would use is entirely set by the maximum sample rate you need to handle. If this is something like 1Msps, use a single 18x18 multiplier and multiplex it, and you can get away with writing behavioral code because the whole thing would only need to run at 48MHz for 6 channels. The dataflow methodology and heavy pipelining is what I do to hit 350MHz on the slowest speed grade Artix.
That is also an option. And a really development time effective approach would be to use a small soft-core like the Picoblaze from Ken Chapman which takes care of the sequencing part using some software.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #17 on: April 18, 2020, 02:21:52 pm »
32x32 multiply (or 36x36) requires  four 16x16 (or 18x18) HW multipliers.

No accumulators after the multiplier.  Just optional registers on both inputs or the output.  Cyclone IV is quite simple FPGA I guess.  Already investigated in the device handbook.
Yes, but do you need 32 bit multiplications? In the end your multiplications don't need to exceed the bit width of the output signal. What is the resolution of the output signal? And I think there are some optimisations possible as well.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #18 on: April 18, 2020, 03:25:20 pm »
I find it highly unrealistic to try bother with any kind of obscure softcore CPU architecture as an FPGA beginner. :-/

Not that sure what width of multiply is really needed. But the other logic supposed to be fed the output from the controller now can accept up to 24 bits.  Could be little less, little more. Not finished with it yet either.

It seems that using the approach of "think first - code later" is much better - to no surprise. It was easy to pursue the sythesizer to produce the thing below.

Now if I'd fill in the missing structure on the B input of the multiplier, I'd have a complete PS controller. Even surprised it required less code to write, than my original version, that synthesized to the garbage I wasn't even sure it worked properly.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #19 on: April 18, 2020, 03:41:49 pm »
I find it highly unrealistic to try bother with any kind of obscure softcore CPU architecture as an FPGA beginner. :-/
You should look into it. The Picoblaze is an extremely simple and yet powerful solution to avoid having to code complex statemachines in VHDL. I have used it in several designs; it could be a good fit for your protect if you want to pipeline the multipliers. Another option is to use a programmable statemachine but the Picoblaze is probably easier.
« Last Edit: April 18, 2020, 03:57:32 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15180
  • Country: fr
Re: FPGA: PID controller (VHDL newbie)
« Reply #20 on: April 18, 2020, 04:50:25 pm »
Just a couple thoughts:
- I think the "hardest" part (if you consider that "hard") here will be to avoid overflows/underflows using fixed-point arithmetic (which I assume here), rather than figuring out how to implement it efficiently; I don't completely disagree with nctnico with this (but I think his naive implementation is probably not dealing with overflows right to begin with?) As many often say, as long as the result fits your requirements in terms of speed and area, it's not necessary to optimize it further unless it's done for just its own sake (and, why not.)
- Pipelining will get you a lot more ROI in terms of speed improvements than any other technique IMO for this,
- Regarding using a CPU soft core, I do agree that it would make it much more difficult especially if you've never used one before. And looks overkill to me for just a PID.

 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: FPGA: PID controller (VHDL newbie)
« Reply #21 on: April 18, 2020, 05:00:44 pm »
- Regarding using a CPU soft core, I do agree that it would make it much more difficult especially if you've never used one before. And looks overkill to me for just a PID.
You are definitely wrong here. Try to figure out the logic and statemachines needed to pipe all the multiplications through one multiplier for 6 channels. It is much easier to implement sequential logic using software than hardware. The Picoblaze was officialle called 'Ken Chapman's Programmable State Machine' and it is just that. It has 4 (IIRC) simple instructions. In case of a PID controller the program can loop over 6 sets of input, setpoint, ki, kp, integrator and output registers. The data itself doesn't flow through the Picoblaze; the Picoblaze only controls the multiplexers to select the input for the multiplier / adder and where to store the result. Sure this approach doesn't get the highest throughput but it is extremely time efficient to develop. The Picoblaze (or something similar) is something which belongs in every FPGA / ASIC designer's toolbox.
« Last Edit: April 18, 2020, 05:02:28 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline YansiTopic starter

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: FPGA: PID controller (VHDL newbie)
« Reply #22 on: April 18, 2020, 05:34:19 pm »
Just wanted to note, that Picoblaze is a product for Xilinx and seems intended to be used only by Xilinx users. I am not sure if it is legal to be used on other vendors FPGAs. Altera (Intel) seems to have some sort of NIOS softCPU.

Regarding the fixedpoint overflow: As I've already stated, only a saturating adder is required. Already implemented that and verified it working.

The current state machine to control the PS controlel is extremely simple three state one. Waiting in idle, then stepping through the other two steps. No other conditions anywhere. Dead easy.

Adding a top level FSM to multiplex through 6 set of inputs and outputs would also be likely straightforward.

(And I almost doubt a simple 8bit softCPU would be even capable of computing 6 PS controllers at any half-decent rate)
 

Offline filssavi

  • Frequent Contributor
  • **
  • Posts: 433
Re: FPGA: PID controller (VHDL newbie)
« Reply #23 on: April 18, 2020, 06:14:12 pm »
Unless you are planning to run the PID at 100/200 MHz ( which in motor control I doubt you want) soft core is the way to go, only one multiplier/ adder needed , don’t bother with micro optimising the architecture, as it is a waste of time (unless you want to learn to do that, in that case optimise away)
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15180
  • Country: fr
Re: FPGA: PID controller (VHDL newbie)
« Reply #24 on: April 18, 2020, 06:18:01 pm »
Just wanted to note, that Picoblaze is a product for Xilinx and seems intended to be used only by Xilinx users. I am not sure if it is legal to be used on other vendors FPGAs. Altera (Intel) seems to have some sort of NIOS softCPU.

That's right. It's free to use... on Xilinx products only.
https://en.wikipedia.org/wiki/PicoBlaze

Regarding the fixedpoint overflow: As I've already stated, only a saturating adder is required. Already implemented that and verified it working.

The current state machine to control the PS controlel is extremely simple three state one. Waiting in idle, then stepping through the other two steps. No other conditions anywhere. Dead easy.

Adding a top level FSM to multiplex through 6 set of inputs and outputs would also be likely straightforward.

(And I almost doubt a simple 8bit softCPU would be even capable of computing 6 PS controllers at any half-decent rate)

It's certain it wouldn't be able to reach the same frequencies and would eat up more resources.
Since you pretty much have it all figured out, I can't see what it would bring to the table.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf