I'm designing a very simplistic microprocessor as a project to help learn VHDL. So I'm needing something to increment the 8 bit program counter. I will need to increment it by two. Is there a better (either faster or less logic required for equal speed) design than using an 8 bit full adder? I'm also interested for the same thing for if you only needed to increment the PC by 1.
-
\$\begingroup\$ I don't know almost anything about VHDL and maybe you take this for granted when you talk about a full adder, so sorry if that's the case, but for improving performance you have the "carry look-ahead adder". \$\endgroup\$– ravenCommented Apr 3, 2011 at 12:17
-
2\$\begingroup\$ BTW: link just in case en.wikipedia.org/wiki/Carry_look-ahead_adder \$\endgroup\$– ravenCommented Apr 3, 2011 at 12:17
-
\$\begingroup\$ @JaimePardos, all ALUs use this or a more advanced device to increase speed. Waiting for 32 carry bit delays is not acceptable in a modern processor. \$\endgroup\$– KortukCommented Apr 4, 2011 at 1:45
5 Answers
Hmmm, this all depends on what exactly you are trying to learn. A counter or adder in VHDL is super easy:
signal count :std_logic_vector (7 downto 0) := (others=>'0');
. . .
process (clk)
begin
if rising_edge(clk) then
if count_enable='1' then
count <= count + 1; -- could be +2 also
end if;
end if;
end process;
And that's it! The VHDL compiler will normally synthesize a full-adder for this, and them optimize out everything that isn't needed-- ending up with some sort of half-adder. The nice thing about doing it this way is that your code is readable and easily understood and the compiler deals with figuring out the best way to implement it.
Now, if you are trying to learn about adders and counters and such then my little code snippet isn't going to help you much. In that case you should implement a half-adder the manual and hard way.
-
\$\begingroup\$ After staring at it for a while trying to figure out a more efficient way, I settled with just using the VHDL provided full adder:
S <= (I) + ("00000010");
\$\endgroup\$– EarlzCommented Apr 3, 2011 at 7:00 -
\$\begingroup\$ Also, a good synthesis tool will automatically choose an appropriate implementation based on your constraints, i.e. ripple if speed isn't important, and CLA or other optimized implementation if it is. \$\endgroup\$– AndyCommented Apr 3, 2011 at 20:32
You don't actually need a full adder for increment by 1; using half adders where the first input is set to 1, and carry bits are daisy chained to the next bit would do. I'm not sure if there's a still better way to do it, though.
Incrementing by two could be done by ignoring the first bit of a number, and using the same method above.
NOTE: not a VHDL expert, can't state if this could actually be faster, but should be less logic.
Edit: Also, there's an expired patent for a simple binary incrementer that might be of interest: http://www.freepatentsonline.com/3989940.pdf
-
\$\begingroup\$ Well, I'm no expert either but I'd assume as long as there are not "loops" in hardware(ie, serial), then less logic should always be better. \$\endgroup\$– EarlzCommented Apr 3, 2011 at 2:54
-
\$\begingroup\$ For your edit. Wow, I had forgotten how dense patent pdfs are. \$\endgroup\$– EarlzCommented Apr 3, 2011 at 5:00
Maybe you can use a binary counter built from JK flip-flops, one where you can load the bit value into each flip-flop, then just toggle the clock. Counting by 2 would mean loading everything but the least significant bit into the counter since that bit never changes.
This probably won't be better than a half-adder implementation, but perhaps it is easier to understand :)
What specifically you need is series of T-triggers + a bunch of AND gates. You should pass 'toggle' signal to bit n only if all previous bits were 1. This is much faster than full adder, does not require carry look ahead and eats way less transistors.
PS. Some time ago I was wondering exactly the same question ;-)
-
1\$\begingroup\$ What you're describing isn't faster in an FPGA than using a normal full or half adder, and takes more logic resources. This isn't intuitive at first, but stick with me here. If you were implementing the logic out of raw gates and flip-flops then you might be right. But FPGAs are not raw gates and flip-flops. FPGAs are fixed but semi-programmable logic structures, and these structures include dedicated carry chains that have been hard-wired to be super fast. Much faster than the "normal logic", and using them frees up the normal logic for, well, normal logic. \$\endgroup\$– user3624Commented Apr 4, 2011 at 2:38
-
\$\begingroup\$ I think carry-chains are generally better used for applications requiring full adders; the key point, though, should be to specify what one wants the hardware to do and let the FPGA software figure out how best to implement it given the chip resources that exist. If there are enough other math-ish things to use up whatever dedicated carry chains exist, an incrementer can be done pretty well in ordinary logic. If carry-chain resources are available, it may be good to use them. The FPGA software should be able to figure it out. \$\endgroup\$– supercatCommented Apr 4, 2011 at 4:22
-
\$\begingroup\$ I don't see where it says it's for an FPGA. I agree with you here. \$\endgroup\$ Commented Apr 4, 2011 at 16:24
It certainly does seem as though there should be a simplification -- after all one of the inputs is limited to a fixed value that is the same every time!
Unfortunately, that's only enough to get a small reduction in number of gates, but not much of a reduction in time to complete. That is because you do get simpler adders -- they only have 1 input plus carry, so the base adders have about 1/3 fewer gates. But the delay is determined by the carries, which are not reduced, they still must ripple up the whole chain. So, you don't get much meaningful speedup. And, if you want to go fast, at least half the gates are dealing with the carries, so that 1/3 gain reduces to about 1/6 fewer gates overall. In the end, roughly the same speed, and 85% of the size of a full adder.