Signed BCD numbers for ALU design  - Page 1
Forum section: electronics / projects

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 06, 2013, 10:51:32 am
content: I have a digital design course term project that asks to design an ALU, using VHDL, that's capable of adding and subtracting two 64-bit signed BCD numbers, and in addition to doing all logical operations on two 64-bit binary numbers. The logical operations are neat and easy to do, but I'm having some trouble figuring out how to make it possible to have signed BCD numbers as inputs for addition and subtraction.I simplified the problem by using 8-bit numbers and I wrote a VHDL description to test the addition of two unsigned BCD numbers. The simulation worked as expected. After that, I decided to approach the problem of signed BCD numbers on paper and that's where I have been having the trouble.I will start with most basic issue I have. If I have an 8-bit BCD number, say 99 in decimal, which is 1001 1001 in BCD of weight 8421, how can I get the signed BCD version of it (-99)? I use 2's complement for binary numbers, but I can't figure out if it applies for BCD, too.

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 06, 2013, 11:12:58 am
content: How about using 10's complement for BCD? It should work fine. So if you have a 4 digit BCD number then 9999 is the same as -1 because 0001 + 9999 = 0.The 10's complement (negative) of any BCD number should be the 9's complement + 1 (just as you can form the 2's complement of a binary number by taking the 1's complement [binary inverse] and adding 1). For example the 9's complement of 0045 would be 9999 - 0045 = 9954; adding 1 gives the 10's complement as 9955. And 9955 + 0045 = 0000.

author: amyk
author_rank: Super Contributor
timestamp: December 06, 2013, 12:08:37 pm
content: You might find inspiration in the x86 instructions DAA and DAS andthese curious applications of them...

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 06, 2013, 12:31:08 pm
content: @dfmischler10's complement is easy to work with when we play with decimal numbers, but when we represent the decimal number in binary, it gets complicated. Take for example the operation 3 - 2. How would that be done in binary using 10's complement of 2? I will try doing it in binary below1001 - 0010 + 0001 = 1000 (10's complement of 2 = 8 in decimal)0011 + 1000 = 1011 ( 3 + 10's complement of 2 ( 8 ) = 11 in decimal)11 is supposed to be 1, but how?Edit:forgot to add 0110 to 1011. That will give 0001 = 1. That's good now. I will play with these numbers on paper to get the feel of it and I will see how I can translate that into circuit blocks.@amykThanks for your contribution, but I'm not into any of this really.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 06, 2013, 04:22:08 pm
content: Well, I've stumbled into another rocky wall. To get things started, this is the circuit that I use for unsigned addition:To allow for signed BCD addition, there would be no interest in the lower part of the diagram since that's only used for correction. The upper 4-bit adder is the point of interest. I would allow my rough block diagram sketch to speak for itself:(Click for enlargement)As you can see, the two 4-bit BCD numbers get inputted into a 'Borrow-based Full Subtractor'; this is to get the 9's complement. I forgot to add a next 4-bit adder stage in which we add '0001' to outputs x and y individually (each output has its own stage) and this is to get the 10's complement.We now go to the first 4-bit binary adder of the BCD adder circuit. As you can see from my sketch, I want a method by which the circuit decides which two input numbers should go into the adder (x and y | x and b | a and y | a and b) based on two control inputs. One for deciding if x or a should go through and another one to decide if y or b should go through. For the designer, this control input would represent the sign of the input number. For example, if C1 (control for x and a) is 1, then x goes through (negative number), otherwise a goes through (positive number).I've been thinking which control circuit to use and I've yet to find an answer, so here I come again looking for helping hands. Also, I would like to read your comment on whether the design would work correctly or not.Edit:would a quadruple two-to-one line multiplexer be good to work as a control circuit?

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 06, 2013, 05:26:07 pm
content: I just want to point out that the reason for getting the 10's complement by first calculating the 9's complement is that there are guaranteed to be no borrows when you subtract the BCD number from all 9's. And I thought maybe you could add the one using the carry in to the lowest stage of the adder.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 06, 2013, 05:35:19 pm
content: How would there be no borrows? 1001 - 0111 will have borrows. This is why I thought of using a borrow-based full subtractor. If you have the time, I would like your advice in regard to my lastest post as I'm about to start writing VHDL descriptions.

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 06, 2013, 05:46:51 pm
content: Yes, there are borrows at the binary level, but never between BCD digits.

author: owl_uk
author_rank: Contributor
timestamp: December 06, 2013, 05:48:01 pm
content: Maybe you need to take a bit of a step back on this. Lets look at 2s compliment in binary for a second. It's cool because you can use the same logic as for unsigned numbers and still get the right answer. That's because it behaves correctly as you go through zero. I'll give an exampleCode unsigned value 2s comp value1110 14 -21111 15 -10000 0 00001 1 10010 2 2So you can see here if you add 1 to the code on the left it goes through zero correctly for 2s compliment and wraps through to zero for unsigned.The other cool thing about 2s compliment is that you can make it wider by extending the top bit, and the numbers still add up. So if you take 1111 - for -1 and you make it wider to 11111 then the extra bit is worth -16, but you've changed -8 to +8, which is adding 16, and ta-da, the value remains the same.Now lets think about BCD.You've basically used normal binary adders and now you're trying to add gaffer tape logic to make it behave like BCD. Maybe you need to design a block which adds 2 4 bit bcd numbers and carries the right amount through. If you make it carry the right amount to the next block then you'll be on the right track. In this context you can think about 10s compliment, etc.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 06, 2013, 09:38:53 pm
content: Thank you for your contribution owl_uk and dfmischler. I've come a long way with the 10's complement approach, so there's no time to rethink in the 2's complement domain. I wrote a VHDL description of the previous proposed design and everything worked great. I made it to the first 4-bit binary adder of the BCD adder. A quad two-to-one multiplexer was used to choose between the negative number (10's complement) and the positive number.One problem that didn't catch my attention until I've come a long way in writing the VHDL description, which is the zero. Say that the user inputted (- 20). The circuit will take 10's complement of each digit as following:0010 0000 (20)The first 4 bits will be processed as following according to my design:1001 - 0000 + 0001 = 1010 (A in hex) > 9I had to add additional logic gates just to change A whenever it occurs into 0000. The solution was a simple 4 input - 4 output table in which binaries from 0000 up to 1001 go through as they're, 1010 changes to 0000 and anything above that is don't care.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 09:51:53 am
content: I've come to a major flaw in the design. Say that we want to add two negative numbers (-9 and -9), the result is -18. Using 10's complement to represent signed BCD numbers, it would be:0001 (-9)+0001 (-9)--> 0010 (-8)But, where's the carry out? the sum is correct, but there must be a carry out so that the sum is 0010 and the carry out is 1. Unfortunately, I didn't count for this flaw when I started the design. Any ideas on how to overcome this flaw neatly?

author: amyk
author_rank: Super Contributor
timestamp: December 11, 2013, 11:33:37 am
content: You're mixing binary and decimal, whereas BCD is usually stored sign-magnitude.

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 11, 2013, 12:34:04 pm
content: Quote from: Abstr7ct on December 11, 2013, 09:51:53 amLet's use more digits so we can evaluate this properly. The 10's complement of 9 is 9990 + 1 = 9991. 9991 + 9991 = 9982. Which is the 10's complement of 18: 9982 + 0018 = 0000.As you will see from the above work there is no carry from the low BCD digit when adding -9 (9991) + -9 (9991). But you can't represent -9 in 4 bits unambiguously because only half of the number circle (modular space) can be for negative numbers (just as is done with 2's complement binary numbers).

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 01:15:01 pm
content: So any suggestions on how to proceed? I'm thinking of two possibilities:1. Keeping the design as it's and accept the flaw. AT LEAST something works!2. Overhaul the design and start thinking from scratch, which is unlikely at this point.

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 11, 2013, 01:33:01 pm
content: What flaw? As I demonstrated there is no carry out needed from the low-order BCD digit in the case you provided.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 01:57:25 pm
content: QuoteI'm not sure that I understand this point well. I understand that a 4-bit signed binary number would accommodate decimals from +7 down to -8 using 2's complement. Would you please elaborate?

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 11, 2013, 02:11:54 pm
content: Quote from: Abstr7ct on December 11, 2013, 01:57:25 pmThe modular space for a 4-bit binary number is 0 to F (16 values). In 2's complement half of the values (0 through 7) are positive and the other half (8 through F) are negative (representing -8 through -1).The modular space for a 4-digit BCD number is 0000 to 9999. If you use 10's complement notation then you will split the modular space in half for positive and negative numbers. So values from 0000 to 4999 are positive, and the values from 5000 to 9999 represent -5000 to -1. Similarly, if you only have one digit, then in 10's complement you can represent from 0 to 4 as positive values, and 5 to 9 represent -5 to -1. So if you have to represent values outside of these ranges then you need to use more BCD digits.If you have 2 BCD digits then you can represent 0 to 49 as positive and -50 through -1 using the remaining values.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 02:41:25 pm
content: I get it now, or I hope so. My design prompts the user to enter two 64-bit BCD numbers. This means that, in the 10's complement domain, each BCD digit (composed of 4 bits) can't actually represent more than +4 or less than -5. The addition of two 8-bit signed BCD numbers, using 10's complement, can't cross 99 or -99, or in other words, there would be no carry whatsoever. The user will be limited to add/subtract two 64-bit BCD numbers in which each digit is between -5 to +4. Is my understanding correct, dfmischler?

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 11, 2013, 02:58:13 pm
content: Quote from: Abstr7ct on December 11, 2013, 02:41:25 pm64-bit BCD values in 10's complement could represent -5000000000000000 to 4999999999999999 (I hope I got that right, I intended to show 16 BCD digits). Only the leading digit is restricted to 0 through 4 for positive and 5 through 9 representing negative. The other digits can have any of the values 0 through 9.QuoteNo. -50 + -50 = -100, which can't be represented in 2 digit 10's complement. Let's see that.-50 would be represented as 50. 50 + 50 = 100 which carries out to the next digit.

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 03:13:39 pm
content: So, the addition of two 8-bit signed BCD numbers, using 10's complement, can't go over 44 neither can go below -55. Also, assuming that we would like to let the user input two 4-bit signed BCD numbers. Since the sum should be 4 bit, too, then he should be careful not to enter two numbers that, when added or subtracted, would cross +4 or -5. Does any of this make sense?

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 04:08:19 pm
content: If each signed BCD digit (composed of 4 bits) can't go more than +4 neither it can go below -5, then a n-bit signed BCD number can only have digits in that range. In other words, numbers like +(49,48,47,46,45) can not exist because the first digit is over +5.The design is set up to process one BCD digit (4 bits) at a time, so that's what I imagine from the long conversation with you, dfmischler. I appreciate your help, and I would like more from you until I get things right or just go ahead and keep things as they're. At this moment, I must say that it turned out that working with signed BCD number is much more complicated than I imagined. It's very tricky and confusing.

author: dfmischler
author_rank: Frequent Contributor
timestamp: December 11, 2013, 05:22:49 pm
content: It is exactly like working with 2's complement and binary. The bottom line is that the hardware that works properly for unsigned BCD will add 10's complement BCD without any changes.

author: owl_uk
author_rank: Contributor
timestamp: December 11, 2013, 07:17:49 pm
content: So lets clarify things.- There are only 16 combinations of 4 bits, so you cant have -9 to +9 and store it in 4 bits.- BCD treats each group of 4 bits as a digit, this is not something you need to think about with binary numbers.- With 2's compliment you can set the first bit as a big negative value, which then effectively moves the binary codes so that 0 is half way up the code space and all of the addition and subtraction logic works.With your BCD system you need to make sure that addition and subtraction around 0 works. You don't need to have way of giving a sign to each digit, or each 4 bit group. Only the whole number (all 64 bits). With 2s compliment the sign belongs to the first bit and the first bit also carries a value. so for a 4 bit 2s compliment value the msb carries the minus sign and the value 8.You could use your 64th bit as a sign. It would mean your first digit in your 64 bit number couldn't be more than 7, but you can then build some 4 bit adder subtractor blocks and carry the sign from one through to the next.I'm not sure if you can use 10's compliment or not in your use case.10's compliment would mean that the meaning of a 4 bit group changes when you know it is negative. So 1000 is 8 when positive and -2 when negative. This has the benefit of making the maths work. If you add 1 to 8 you get 9 , if you add 1 to -2 you get -1.But imagine you connected all of these 4 bit groups to a 7 segment decoder to show the number. If it is your decoder then you'd can modify your display logic with 10s compliment. If it is some decoder logic that has already been made, then you have a problem.So that gives you your second option, which is just to have a - sign which is turned on or off by bit 64. Which would work with even the simplest of display logic. The down side here is that the maths functions become more complicated.I think the main thing your excercise shows is that BCD is a big pain in the arse!

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 11, 2013, 09:26:57 pm
content: Thank you, dfmischler and owl_uk, for your efforts. I decided to stop and keep on with the current design. The only thing that I've come to understand is that I don't really understand how signed BCD numbers can be represented. I even tried doing some Google search and I found that there's a lack to non-existing pages on the subject. I only found this article from EDN network, which is titledEven more mind-boggling math: Working with signed BCD. It's linked below:http://www.edn.com/design/systems-design/4322091/Even-more-mind-boggling-math-Working-with-signed-BCDI would've been glad if the project asked for normal signed binary numbers as this would've been very easy to design, but BCD is a question mark for me?!!Thanks.

author: baljemmett
author_rank: Unknown
timestamp: December 11, 2013, 11:23:38 pm
content: Quote from: Abstr7ct on December 11, 2013, 04:08:19 pmNo - I think you're confusing the range of a ten's-complementnumberwith the values of a BCDdigit.The digits themselves will always be in the range 0..9 with the usual meanings - that's it, no negatives, you don't need to worry about that at all when doing arithmetic - nice and simple.The use of some numbers as negative values applies to the number as a whole, not to each individual digit. So, if we take a four-digit number as an example, we have the (unsigned) values 0000 - 9999, which if we're using ten's-complement can be used to represent the range -5000 - 4999. Values between 0000 and 4999 simply mean their normal positive value, and those between 5000 and 9999 represent the negative numbers -5000 to -1 respectively. It's only the most-significant digit that can't be greater than 4 before the number as a whole becomes negative.How does this work in practice, when doing BCD arithmetic? Let's try your -9 + -9 example:-9 represented as a four-digit ten's-complement number is 9991 (subtract 9 from 10000, or if you prefer you can subtract each digit from 9 individually (-> taking the nine's complement) and then add one to the result)9991 + 9991 = 19982 (completely normal arithmetic; if you want to do it BCD-digit-by-BCD-digit it's just 1 + 1 = 2 with no carry, 9 + 9 = 8 carry 1, 9 + 9 + 1 = 9 carry 1, etc.)But 19982 = 9982 because we've only got four digits to work with - the final carried 1 has fallen off the end… and 9982, read as ten's-complement, is -18; everything works!Now, you can try the same thing with sixteen digits (your 64-bit numbers), or ten digits, or three digits, or two digits and it'll work fine - but it won't work if you only have a one-digit number, because you can't represent -9 as a one-digit ten's-complement number - it would be 1, which is just 1! You need to have at least two digits before the most-significant digit is big enough to be in the 'top'/'negative' half of the range, giving you 91 = -9. Similarly you can't represent 5 as a one-digit ten's-complement number, because 5 represents -5; you need at least one more digit (05) instead.(Note that you have the same range problem if you're using two's-complement for normal binary arithmetic; a one-bit number can be 0 (0) or -1 (1), a two-bit number can be 0 (00), 1 (01), -2 (10) or -1 (11) - if you want to represent 2 (010) or -3 (101) you need at least three bits, because without that top bit you've just got -2 or 1 respectively!)It might seem a little complicated, but you can actually ignore all the complexity entirely as long as you have enough digits to represent your numbers - the beauty of using ten's-complement for decimal/BCD arithmetic, or two's-complement for binary, or in general N's-complement for any base N, is that you don't have to care about whether a number is positive or negative at all for the maths to work. You just add two N's-complement numbers in the same way you always do - digit-by-digit, with carries, as if they were just unsigned numbers - and then what you're left with is a number that, read as N's-complement, has the right value. The fact that the numbers you put in may have been negative, and the number you got out might be negative, is just representational - it's all in how you interpret the digits. The maths doesn't care, and nor does your BCD adder circuit.Quote from: Abstr7ct on December 11, 2013, 09:26:57 pmI'm not sure if any of my waffle has helped at all, but given this comment it sounds like you should get there once it 'clicks'. The upshot is, really, as long as you have a BCD adder circuit, it will work when fed ten's-complement numbers in just the same way as a binary adder would would work when fed two's-complement numbers, which I presume you're referring to with 'normal signed binary numbers'. (There are other forms of signed binary numbers - one's-complement, for instance, or sign and magnitude - but you'll find they're relatively unpopular because they're more complicated to do arithmetic with compared to two's complement, where the numbers can just be treated as if they were unsigned.)

author: owl_uk
author_rank: Contributor
timestamp: December 12, 2013, 02:03:03 pm
content: QuoteOh I get it now. So if we stick to 4 digits for simplicity, you get 9999 for -1, 9998 for -2, etc. And you can use your normal adders/subtractors. And if it starts with a 9 it's negative, otherwise it isn't. You still then need some logic if you want to display the number correctly, though, right? You can't just connect the bits to a 7 seg decoder like you can with an unsigned BCD number. Also it isn't a simple matter of mapping digits, because 9999 becomes -0001. So 9 maps to '0' for the first 3 digits and '1' for the last. Is there an easy trick to fix this?

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 12, 2013, 09:09:19 pm
content: I think that it somewhat clicks with me now. I don't want to go into more details about how I understand signed BCD using 10's complement, nor how the whole arithmetic circuit would be designed, but I've the idea that the circuit would need someconversionlogic. Say that the user has the opportunity to enter a signed BCD digit (composed of 4 bits) from 0-9, signed or unsigned, then the output must be converted into 8 bits. For example, if the user inputs -6, then the converter must output 94 (1001 0100). Is this correct?

author: Abstr7ct
author_rank: Regular Contributor
timestamp: December 13, 2013, 12:36:55 pm
content: Say that the user would like to perform the operation (-9-9). The circuit should allow him to input 1001 for number1 and 1001 for number2. It will take 1001 and perform 4 bits-to-8 bits conversion logic inside for each number. 1001 0001 (the 10's complement of 09 which is -9) will be one input of a 2X quad 2-to-1 multiplexer. The second input is the normal positive number expanded into 8 bits (0000 1001 = 09). The control line of the Mux will determine if the 8-bits output would be the normal number (0000 1001) or the 10's complement (1001 0001), and this decision goes back to the user.Let me do the operation in binary:1001 0001+1001 0001----------------------1 ---> carry out (don't care about it in the design, but may be useful to indicate a negative value for decoding/display purposes)0010 00100110 ---------> this is for BCD correction (add 6)------1000 0010 = 82 --> This would be the negative (10's complement) representation of 18.The sum will have a double number of bits compared to the input coming from the user. A 64-bit input of 16 BCD digits will have a 128-bit output (16×8) since each BCD digit will be represented by 8 bits inside.How is that design flow?