Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Need help with converting binary to BCD

Status
Not open for further replies.

Kepsz

Member level 1
Joined
Feb 7, 2012
Messages
32
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,521
I trying to implement this methode of binary to bcd conversation: It uses the shift 3x -> add + 3 if grather than 5 -> shift 1x methode.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity hex_to_bcd is
	port (
		CLK_in:		in std_logic;
		INPUT:	in	std_logic_vector(15 downto 0));
end hex_to_bcd;

architecture Behavioral of hex_to_bcd is
	signal bcd_0 : std_logic_vector( 0 to 19);
	signal bcd_1,bcd_2,bcd_3,bcd_4,bcd_5 : std_logic_vector( 0 to 4);
	signal int_1,int_2,int_3,int_4,int_5 : integer range 0 to 32;
begin
	Process (CLK_in, INPUT)
	begin
		if (rising_edge(CLK_in)) then
			bcd_0 <= to_stdlogicvector(to_bitvector("0000" & INPUT) sll 3);
			bcd_1 <= "0" & bcd_0(16 to 19);
			bcd_2 <= "0" & bcd_0(12 to 15);
			bcd_3 <= "0" & bcd_0(8 to 11);
			bcd_4 <= "0" & bcd_0(4 to 7);
			bcd_5 <= "0" & bcd_0(0 to 3);
			int_1 <= to_integer(unsigned(bcd_1));
			int_2 <= to_integer(unsigned(bcd_2));
			int_3 <= to_integer(unsigned(bcd_3));
			int_4 <= to_integer(unsigned(bcd_4));
			int_5 <= to_integer(unsigned(bcd_5));
		end if;
	end process;
end Behavioral;

This code works, grabs the 16 bit from the input, then puts them to a 20 bit long vector, after four zeros (like 000011010011....), where shifts them left by 3 bits. The next stage separates the 20 bit to 5*4bit, then put the 4 bits to a 5 bit long vector, after a zero (like 01001). This first zero will be the carry. But after that i stuckd, if i convert values to integer, it's just made simple conversations like 00110 to 110 integer, instead of 6.

So I looking for a way to manipulate the vectors, adding "00001" and "00101" to them. If this is not possible with vectors, maybe in integer or something else.

This module will be part of my Spartan3E kit's design. Now my kit shows it's ADC's output value in 7 segments display like F3E instead of 3902 decimal.
 

Theres a few odd bits here:
bcd_0 <= to_stdlogicvector(to_bitvector("0000" & INPUT) sll 3);

is the same as
bcd_0 <= '0' & INPUT & "000";

And then I dont understand the rest of th code. You are simply extracting a load of bits and converting them to integers. THis is not a BCD converter.
 

Kepsz, don't get too caught up in deciphering methods. Remember, you are dealing with the same number regardless of it's representation. In other words, any number can be represented in any number of different bases. In this case, why not convert binary to decimal, then it's a simple matter to convert each digit to a BCD nibble.
 

Thanks, bcd_0 <= "0" & INPUT & "000"; is works.


I made some clearing in the code, now all vectors directed in the same way.
Code:
architecture Behavioral of hex_to_bcd is
	signal bcd_0 : std_logic_vector( 19 downto 0);
	signal bcd_1,bcd_2,bcd_3,bcd_4,bcd_5 : std_logic_vector( 4 downto 0);

begin
	Process (CLK_in, INPUT)
	begin
		if (rising_edge(CLK_in)) then
			bcd_0 <= "0" & INPUT & "000";
			bcd_5 <= "0" & bcd_0(19 downto 16);
			bcd_4 <= "0" & bcd_0(15 downto 12);
			bcd_3 <= "0" & bcd_0(11 downto 8);
			bcd_2 <= "0" & bcd_0(7 downto 4);
			bcd_1 <= "0" & bcd_0(3 downto 0);

Forget about the integer things, that was just an experiment. So currently when my code grabs the input like 1010110010101101, then it splits them to:

bcd_0 "01010110010101101000" - shift 3x left done

bcd_1 "01000"
bcd_2 "00110" -ones
bcd_3 "00101" -tens
bcd_4 "00110" -hundreds
bcd_5 "00101" -thousends

Now i can determine, which bcd_2...5 is bigger than "00101" with a simple if statment. But i don't know, how to add a binary value to a vector. Like "AluPin" wrotes down here: How to add an binary value to a vector?


gary95329: If i understand u correctly, i want to do what u sad.
 

they way you've split it up, is not in base 10. Its in base 2. so assuming the input is unsigned:

bcd_1 is ones
bcd_2 is 2^5 s (ie each bit represents 32)
bcd_3 is 2^10 (ie each bit represents 1024)

So its no ones, tens, hundreds etc.

To add a "binary" value to a vector, you need to convert them to unsigned (with output1 being an unsigned)

output1 <= unsigned(bcd_1) + "00101";

You cannot do arithmatic with std_logic_vector (it wouldnt make sense, because do you want signed or unsigned?)
 
  • Like
Reactions: Kepsz

    Kepsz

    Points: 2
    Helpful Answer Positive Rating
Now i figured out, the rutine is much more complicated, when the input is 16 bit "long"... o_O

I have founded this ppt https://www.google.hu/url?sa=t&rct=j&q=16%20bit%20binary%20to%20bcd%20conversion&source=web&cd=1&sqi=2&ved=0CCMQFjAA&url=http%3A%2F%2Fwww.cse.secs.oakland.edu%2Fhaskell%2FCSE378%2FLectures%2FWinter2006%2FD4.5%2520Binary2BCD.ppt&ei=bYcyT42YMbD44QT9vYmgBQ&usg=AFQjCNFDTl7kDaxgoiUl10HvHZ4uasF5bQ&cad=rja, which contains te vhdl code for 16bit converter.

I merged it with my code, edited it to use only numeric_std, and now its working. (results checked with this online calculator: Binary to BCD Converter - Convert Binary to Binary-coded Decimal)

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity hex_to_bcd is
	port (
		CLK_in:		in std_logic;
		INPUT:	in	std_logic_vector( 15 downto 0 );
		BCD_OUTPUT:		out std_logic_vector ( 18 downto 0 ));
end hex_to_bcd;

architecture Behavioral of hex_to_bcd is
begin
	Process (CLK_in, INPUT)
		variable temp: unsigned (34 downto 0);
	begin
		if (rising_edge(CLK_in)) then
			for i in 0 to 34 loop
				temp(i) := '0';
			end loop;
			temp(18 downto 3) := unsigned(INPUT);
		*	for i in 0 to 12 loop
				if temp(19 downto 16) > "0100" then	
					temp(19 downto 16) := temp(19 downto 16) + "0011";
				end if;
				if temp(23 downto 20) > "0100" then	
					temp(23 downto 20) := temp(23 downto 20) + "0011";
				end if;
				if temp(27 downto 24) > "0100" then	
					temp(27 downto 24) := temp(27 downto 24) + "0011";
				end if;
				if temp(31 downto 28) > "0100" then	
					temp(31 downto 28) :=  temp(31 downto 28) + "0011";
				end if;
					temp(34 downto 1) := temp(33 downto 0);
			end loop;
			BCD_OUTPUT <= std_logic_vector(temp(34 downto 16));
		end if;
	end process;
end Behavioral;

I'm not exactly sure about what is happaning inside the for cycles.
 

The first for loop simply sets all the bits to zero. Could be replaced with:
temp <= (others => '0');

or in keeping with the type:
temp <= to_unsigned(0, temp'length);

The other loops simply add 3 until the number is greater than 4. The problem with these loops is that when synthesised, it will unroll into worst case, so actually what you have is a set of 12 comparitors and adders in series (with a shift inbetween each set). Loops are unrolled into serieal hardware. This means with a long chain between registers, the fmax is going to be pretty low. Better to pipeline it (yes it would take 12 clocks to get an answer) but the FMAx would be way up.
 
  • Like
Reactions: Kepsz

    Kepsz

    Points: 2
    Helpful Answer Positive Rating
Now i generated the bitstream and downloaded it to my starter kit. Works beautifull. Meassuring 3.3V with 12bit dac is now shows ~4090 in 7 segment displays instead of ~FE7 something. :)

My kit's clock source is 50MHz, the DAC is operates at 12.5MHz (internaly generated for the built-in IC's), so new data arrives to bin - bcd converter with every fourth clock pulse. That's means every fourth new data processed in the converter, staying 12.5MHz "output".
I will send the BCD values to an RS232 -> USB converter modul and write them to a file in a Linux PC.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top