5
\$\begingroup\$

I'm having trouble displaying a binary number into a display. I'm not sure of how to split a number in binary into its individual numbers.

For example, if I want to display 25, I want to split this into "2" and "5" in binary. I have 8 bits coming in and would like to split it into two 4 bit parts with the first 4 bits representing the first digit in binary and second 4 bits representing the second digit in binary.

EDIT: To clarify, I'm trying to do this using logic gates.

\$\endgroup\$
  • \$\begingroup\$ What programming language are you using? Or aren't you using a micro and are you looking for some logic gates solution? \$\endgroup\$ – user17592 Apr 5 '13 at 15:08
  • \$\begingroup\$ I'm looking for a logic gate solution. \$\endgroup\$ – John Smith Apr 5 '13 at 15:19
  • \$\begingroup\$ Do you want to do this using actually discrete logic, or by designing it in Verilog or VHDL? \$\endgroup\$ – Rocketmagnet Apr 5 '13 at 15:25
  • \$\begingroup\$ I'm using logisim but a general representation would also be fine I think. \$\endgroup\$ – John Smith Apr 5 '13 at 15:27
11
\$\begingroup\$

The Double-dabble technique converts binary to BCD by repeated shifting. Each repetition halves the remaining binary number and doubles the BCD number, after the complete binary value is shifted the result is obtained. After each shift a correction is applied to each 4-bit BCD column (or those having more than 3 bits shifted in by that point). This correction looks for digits that will 'BCD overflow' decimal 9 -> 10 on the next shift and patches the result by adding three.

Why three? BCD digits in the range zero to four (0,1,2,4) will double naturally to 0,2,4,8 after the shift. Examining 5 b 0101, that will shift to b 1010 (0xA), which is not a BCD digit. 5 is therefore corrected to (3+5) i.e. b 1000 (0x8) which during the shift doubles to 16 decimal (0x10), representing a carry out of 1 to the next digit and the expected zero.

Implementations repeat this process, either synchronously in time using a shift register and 'n' cycles for an n-bit input, or in space by placing the logic circuits for the correction feeding each other and doing the shift with wiring. There is a carry path right through every digit, and the carry logic is not suited to FPGA (binary) carry chain logic, so the space implementation generally gives unacceptable timing results for large inputs. A typical engineering trade-off.

For a parallel (asynchronous) conversion

For narrow values like yours Dr. John Loomis's site has a guide to the logic structure required to implement in hardware. Modern reprogrammable logic can do 8 bits wide to maybe 100mhz after aggressive synthesis. The module add3 takes a 4-bit input and outputs it verbatim, or if more than four, adds three:

module add3(in,out);
input [3:0] in;
output [3:0] out;
reg [3:0] out;

always @ (in)
    case (in)
    4'b0000: out <= 4'b0000;  // 0 -> 0
    4'b0001: out <= 4'b0001;
    4'b0010: out <= 4'b0010;
    4'b0011: out <= 4'b0011; 
    4'b0100: out <= 4'b0100;  // 4 -> 4
    4'b0101: out <= 4'b1000;  // 5 -> 8
    4'b0110: out <= 4'b1001;  
    4'b0111: out <= 4'b1010;
    4'b1000: out <= 4'b1011;
    4'b1001: out <= 4'b1100;  // 9 -> 12
    default: out <= 4'b0000;
    endcase
endmodule

Combining these modules together gives the output. modules together

For a sequential (multi-cycle, pipelined) variant

For wide signals a serial technique described in Xlinx App Note "XAPP 029" runs 1-bit per cycle, probably at 300mMhz+.

If anyone knows a good hybrid technique I'd be interested to know it. I modelled both in Verilog with test benches in my verilog-utils collection.

\$\endgroup\$
  • \$\begingroup\$ I like the Xilinx approach; it's simple, and it allows for compact (though not necessarily fast) code on microprocessors which include instructions for BCD arithmetic. If one really doesn't need speed, the Xilinx approach can be adapted to generate long decimal outputs with a single 4-bit BCD unit along with a bunch of shift registers. Of course, for a two-digit number that's not really necessary. \$\endgroup\$ – supercat Apr 5 '13 at 16:29
1
\$\begingroup\$

What you want to do it known as conversion to Binary Coded Decimal. Some computers have special instructions to help with conversion to and from BCD, and to help with addition and subtraction. However, that's of no relevance to you.

The simplest way I know to convert your 8-bit number into two 4-bit numbers is to handle it in powers of 10.

unsigned char eight_bit_to_two_four_bit(unsigned char value)
{
    unsigned char result = 0;

    while (value >= 10)        // First, count how many 10s fit into value
    {
        value -= 10;
        result += 0x10;        // and count them in the top 4-bits of result
    }

    result += value;           // The remainder is the number of 1s in value
                               // These end up stored in the bottom 4-bits of result

    return result;
}

The while loop there is basically implementing a divide operation. Another way to implement this function is:

unsigned char eight_bit_to_two_four_bit(unsigned char value)
{
    unsigned char result = 0;

    result  = (value / 10) << 4;
    result += (value % 10);

    return result;
}

This actually uses two divide operations. Expensive! Instead we can replace one of the divides with a multiply and subtract.

unsigned char eight_bit_to_two_four_bit(unsigned char value)
{
    unsigned char result = 0;

    result  = (value / 10) << 4;
    result += (value - result*10);

    return result;
}

The fact that this function is implemented with divides probably makes it tricky to implement with combinatorial logic. To do this in pure logic, the best approach is probably to try to implement the first function.

\$\endgroup\$
  • \$\begingroup\$ That's what I would do too. Too bad he's looking for a logic gate solution... \$\endgroup\$ – user17592 Apr 5 '13 at 15:20
  • \$\begingroup\$ Sorry, I understand how to do this logically but not too sure how to do it using logic gates. \$\endgroup\$ – John Smith Apr 5 '13 at 15:21
  • \$\begingroup\$ @YamatoC - It's the same algorithm if you want to use logic gates. You'll need to implement division and modulo operations in your logic. These are somewhat complex calculations to do, but if you search for division algorithms you should be able to find something that's implementable. \$\endgroup\$ – Tim Apr 5 '13 at 15:31
1
\$\begingroup\$

Are you looking for a binary to BCD converter like the 74185?

If not, there's a list of 7400 series logic chips on Wikipedia you could look through and find what you need.

\$\endgroup\$
0
\$\begingroup\$

A logic gate solution is straight forward using a truth table and Karnaugh maps. The truth table will have the binary value as its input and the desired BCD value for the output.

Your truth table should look like this:

a0 a1 a2 a3 | b6 b5 b4 b3 b2 b1 b0 <br>
0  0  0  0  | 0  0  0  0  0  0  0
0  0  0  1  | 7-seg output for 1
0  0  1  0  | 7-seg output for 2
and so on

Then convert the truth table into Karnaugh maps (K-maps) and solve for b6, b5 ... b0. Take the resulting equations and implement them using logic gates.

Information on K-maps: http://en.wikipedia.org/wiki/Karnaugh_map

And here is a solution going through a similar execrcise using Nand gates: http://circuitscan.homestead.com/files/digelec/bcdto7seg.htm

Edit: From the comments: If your 4-bit number doesn't strictly represent a BCD i.e it goes beyond 9 then I'd derive the equation directly from the truth table. So for example for this entry in the truth table:

a0 a1 a2 a3   | output
0   1  0  1   | 0 1 1 0 1 1 0

your equation for the first bit (0) is a0 + a1 (bar) + a2 + a3 (bar), 2nd bit (1) is a0 (bar) + a1 + a2 (bar) + a3 and so forth. Implementing these equation in logic gates is straight forward.

Edit2: Many of these equations will overlap and you will be able to simplify further after generation.

\$\endgroup\$
  • 2
    \$\begingroup\$ For a 2 (decimal!) digit number that will be quite a large truth table. \$\endgroup\$ – pjc50 Apr 5 '13 at 15:37
  • \$\begingroup\$ The truth table only needs to be computed once for a 4 bit input. The same equations will apply to the 2nd 4-bit number. \$\endgroup\$ – xyzio Apr 5 '13 at 15:41
  • \$\begingroup\$ The input is actually 7 bits, not 4 bits. The input range is [0..99], which requires 7 bit storage. \$\endgroup\$ – Rocketmagnet Apr 5 '13 at 15:42
  • \$\begingroup\$ @xyzio No, the truth table depends on 4 bits + BCD carry from the previous digit \$\endgroup\$ – shuckc Apr 5 '13 at 15:47
  • \$\begingroup\$ Ah, I did a literal reading of the question where 4 bits = 1 BCD digit which implies the 4 bits only hold values up to 9. If this is the case then I would cheat and derive direct equations from the truth table. 7-digit k-map will be unwieldy. \$\endgroup\$ – xyzio Apr 5 '13 at 16:00
0
\$\begingroup\$

If you want to make the circuit as simple as possible I would recommend that instead of displaying in decimal you use hexadecimal. In that case each 7 segment display shows a value from 0 to 15 where the numbers 10, 11, 12, 13, 14 and 15 are shown as A,B,C,D,E and F. Then you just need two MC14495 IC's to convert each 4 bit value into its 7 segment display outputs.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.