Hi Jason,
I found your algorithm in C (see source after the vhdl code) on the net.
It's cool.
I rewrited your code like this (see bellow) and it works fine (I tested):
(bin and bcd width (20 and 24) could be replaced by constants (C_BIN_WIDTH,
C_BCD_WIDTH)).
Hope this will help.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bin2bcd is
port(
i_clk : in std_logic;
i_rst_an : in std_logic;
i_load_data : in std_logic;
i_data : in std_logic_vector(20-1 downto 0);
o_data_rdy_q : out std_logic;
o_data_q : out std_logic_vector(24-1 downto 0)
);
end bin2bcd;
architecture rtl of bin2bcd is
begin
--------------------------------------------------------------------------
----
-- register mapping:
--
-- ------------------------
-- | v_bcd_bin_q |
-- ------------------------
-- | av_bcd_q | |
-- ------------------------
-- | | av_bin_q |
-- ------------------------
-- |xxx| 3 bits overlaps to save 3 clk cycle processing and 3
dff
--
--------------------------------------------------------------------------
----
ps_bin2bcd : process (i_rst_an, i_clk)
variable v_cnt_q : integer range 0 to 17;
variable v_en_shift_q : std_logic;
variable v_data_rdy_q : std_logic;
variable v_bcd_bin_q : unsigned(20+24-3-1 downto 0);
alias av_bin_q : unsigned(20-1 downto 0) is v_bcd_bin_q(20-1 downto 0);
alias av_bcd_q : unsigned(24-1 downto 0) is v_bcd_bin_q(20+24-3-1 downto
20-3);
begin
if i_rst_an = '0' then
v_cnt_q := 0;
v_en_shift_q := '0';
v_bcd_bin_q := (others => '0');
v_data_rdy_q := '0';
elsif rising_edge(i_clk) then
if i_load_data = '1' then
av_bcd_q := (others => '0');
av_bin_q := unsigned(i_data);
v_cnt_q := 0;
v_en_shift_q := '1';
v_data_rdy_q := '0';
elsif v_cnt_q = 17 then
v_bcd_bin_q := v_bcd_bin_q; -- optional assignment
v_cnt_q := v_cnt_q; -- optional assignment
v_en_shift_q := '0';
v_data_rdy_q := '1';
elsif v_en_shift_q = '1' then
for i in 0 to 5 loop
if av_bcd_q(4*i+3 downto 4*i) >= 5 then
av_bcd_q(4*i+3 downto 4*i) := av_bcd_q(4*i+3 downto 4*i) + 3;
end if;
end loop;
v_bcd_bin_q := v_bcd_bin_q sll 1;
v_cnt_q := v_cnt_q + 1;
v_en_shift_q := v_en_shift_q; -- optional assignment
v_data_rdy_q := v_data_rdy_q; -- optional assignment
else
v_bcd_bin_q := v_bcd_bin_q; -- optional assignment
v_cnt_q := v_cnt_q; -- optional assignment
v_en_shift_q := v_en_shift_q; -- optional assignment
v_data_rdy_q := v_data_rdy_q; -- optional assignment
end if;
end if;
o_data_q <= std_logic_vector(av_bcd_q);
o_data_rdy_q <= v_data_rdy_q;
end process;
end rtl;
**********C source code************
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define BIN_SIZE 4
#define MSB_MASK 0x80000000L
#define BCD_SIZE 13
typedef unsigned long BIN;
typedef unsigned char BCD[BCD_SIZE];
main()
{
BIN bin1,bin;
BCD bcd;
int i,j,k,carry;
char temp[9];
printf("enter number:");
scanf("%lu", &bin1);
bin=bin1;
for (i=0; i<= BCD_SIZE; i++) bcd[i]=0;
printf("\n BCD BIN\n");
for (i=0; i<8*BIN_SIZE; i++) {
/* check for overflow */
for (j=0; j<BCD_SIZE; j++) {
if (bcd[j] >= 5) {
bcd[j] += 3;
/* printout for checking */
for (k=BCD_SIZE; k--; ) printf("%4s ", itoa(bcd[k],temp,2));
printf(" %x\n", bin);
}
}
/* shift right */
carry = (bin & MSB_MASK) == MSB_MASK;
bin = bin << 1;
for (j=0; j<BCD_SIZE; j++) {
bcd[j] = (bcd[j] << 1) | carry;
carry = (bcd[j] & 0x10) == 0x10;
bcd[j] = bcd[j] & 0xF;
}
/* printout for checking */
for (k=BCD_SIZE; k--; ) printf("%4s ", itoa(bcd[k],temp,2));
printf(" %x\n", bin);
}
printf("BIN = %lu\n", bin1);
printf("BCD = ");
for (k=BCD_SIZE; k--; ) printf("%d", bcd[k]);
}
regards
FE
"Jason Berringer" <
[email protected]> wrote in message
news:
[email protected].. .
> Here is the code (after my text) instead of an attachment in case others
> cannot read it.
>
> It takes (or should take) 20 to 21 clock cycles to get the data from the
> input to the output. I put a few numbers through the simulation the only
> correct values are 0 and 1, all other tested were incorrect. I'm pretty
sure
> it's a simple error that I'm not catching, I just can't see it at present.
> Most of the stuff that I have done has been a bit more simple than this.
The
> algorithm works from a sample I've seen (no code just an explanation).
Start
> by shifting the most significant bit of your binary number into the least
> significant bit of your "units" bcd value, when the number in the "units"
> value is 5 or greater add 3 to it. Shift again, if the value is 5 or
greater
> add 3 to it, the values will continue to spill over to the "tens",
> "hundreds", "thousands", etc. You must add 3 to each of the bcd digits if
> any is five or greater, by the last shift (same number of shifts as your
> input binary value (in my case 20 bits)) you'll have the bcd
representation.
> The example I mentioned above was for a microcontroller.
>
> Code
>
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.std_logic_unsigned.all;
>
> entity bin2bcd is
> port(
> clk : in std_logic;
> reset : in std_logic;
> load_data : in std_logic;
> data_in : in std_logic_vector(19 downto 0);
> data_ready : out std_logic;
> data_out : out std_logic_vector(23 downto 0)
> );
> end bin2bcd;
>
> architecture behaviour of bin2bcd is
>
> signal ser_out_s : std_logic;
> signal shift_en_s : std_logic;
> signal data_ready_s : std_logic;
> signal count_s : std_logic_vector(4 downto 0);
> signal bin_in_s : std_logic_vector(19 downto 0);
> signal bcd_out_s : std_logic_vector(23 downto 0);
>
> begin
>
> process (reset, clk) begin
> if reset = '1' then
> count_s <= (others => '0');
> shift_en_s <= '0';
> data_ready_s <= '0';
> elsif rising_edge(clk) then
> if load_data = '1' then
> count_s <= (others => '0');
> shift_en_s <= '1';
> elsif count_s = "10011" then
> count_s <= (others => '0');
> shift_en_s <= '0';
> data_ready_s <= '1';
> else
> count_s <= count_s +1;
> data_ready_s <= '0';
> end if;
> end if;
> end process;
>
> process (reset, clk) begin
> if reset = '1' then
> bin_in_s <= (others => '0');
> elsif rising_edge(clk) then
> if load_data = '1' then
> bin_in_s <= data_in;
> end if;
> if shift_en_s = '1' then
> bin_in_s <= bin_in_s(18 downto 0) & '0';
> end if;
> end if;
> end process;
>
> ser_out_s <= bin_in_s(19);
>
> process (reset, clk, load_data)
>
> variable bcd_value : std_logic_vector(23 downto 0);
>
> begin
>
> if reset = '1' or load_data = '1' then
> bcd_value := (others => '0');
> elsif rising_edge(clk) then
> if shift_en_s = '1' then
> bcd_value := bcd_value(22 downto 0) & ser_out_s;
> bcd_out_s <= bcd_value;
> if bcd_value(3 downto 0) >= "0101" then
> bcd_value(3 downto 0) := bcd_value(3 downto 0) + "0011";
> end if;
> if bcd_value(7 downto 4) >= "0101" then
> bcd_value(7 downto 4) := bcd_value(7 downto 4) + "0011";
> end if;
> if bcd_value(11 downto 8) >= "0101" then
> bcd_value(11 downto 8) := bcd_value(11 downto 8) + "0011";
> end if;
> if bcd_value(15 downto 12) >= "0101" then
> bcd_value(15 downto 12) := bcd_value(15 downto 12) + "0011";
> end if;
> if bcd_value(19 downto 16) >= "0101" then
> bcd_value(19 downto 16) := bcd_value(19 downto 16) + "0011";
> end if;
> if bcd_value(23 downto 20) >= "0101" then
> bcd_value(23 downto 20) := bcd_value(23 downto 20) + "0011";
> end if;
> end if;
> end if;
> end process;
>
> process (reset, clk) begin
> if reset = '1' then
> data_out <= (others => '0');
> data_ready <= '0';
> elsif rising_edge(clk) then
> if data_ready_s = '1' then
> data_out <= bcd_out_s;
> end if;
> data_ready <= data_ready_s;
> end if;
> end process;
>
> end behaviour;
> "Glen Herrmannsfeldt" <
[email protected]> wrote in message
> news:GLFVa.9117$cF.3056@rwcrnsc53...
> >
> > "Glen Herrmannsfeldt" <
[email protected]> wrote in message
> > news:MzFVa.9078$cF.2637@rwcrnsc53...
> > >
> > > "Jason Berringer" <
[email protected]> wrote in message
> > > news:
[email protected].. .
> > > > Hello, I have attached a portion of code for a binary to bcd
counter,
> 20
> > > > bits parallel input, and a 24 bit BCD output parallel. Although
> > internally
> > > > it converts it to serial to go through the conversion. I'm
attempting
> > the
> > > > shift and add three (if greater than or equal to 5) method, but I am
> > > having
> > > > some problems. It works great on the simulator (Aldec Active HDL)
and
> I
> > > can
> > > > synthesize it but when I put it on the chip I'm getting some odd
> things.
> > I
> > > > am using 16 input toggle switches and i debounced pb switch as a
load
> > > > switch, and my outputs are LEDs. When I set this up on the board my
> > > outputs
> > > > go as follows:
> > >
> > > The attachment didn't come through. Can you just include some of the
> code
> > > in the body, instead of an attachment?
> >
> > OK, it did come through but I was looking in the wrong place. Still, it
> is
> > often easier just to include it.
> >
> > I am much better at reading verilog than VHDL, but it doesn't look right
> to
> > me. Though I think I don't understand the algorithm, I think it needs
to
> be
> > more complicated than that, though if you do an iterative algorithm it
> might
> > not be so hard. How many clock cycles does it take to get the data
from
> > input to output? How many different values did you put through the
> > simulator in testing?
> >
> > -- glen
> >
> >
>
>