Re: binary to BCD assistance

Discussion in 'VHDL' started by Glen Herrmannsfeldt, Jul 30, 2003.

  1. "Jason Berringer" <> wrote in message
    news:kJCVa.3413$...
    > 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?

    -- glen
    Glen Herrmannsfeldt, Jul 30, 2003
    #1
    1. Advertising

  2. "Glen Herrmannsfeldt" <> wrote in message
    news:MzFVa.9078$cF.2637@rwcrnsc53...
    >
    > "Jason Berringer" <> wrote in message
    > news:kJCVa.3413$...
    > > 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
    Glen Herrmannsfeldt, Jul 30, 2003
    #2
    1. Advertising

  3. "Jason Berringer" <> wrote in message
    news:IlGVa.3393$...
    > 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.


    As I said, I read Verilog much better than VHDL. I didn't even notice the
    loop yesterday, which is why I didn't think it was complicated enough. OK,
    thought for today:



    (snip)

    > elsif rising_edge(clk) then


    Does the following generate a gated clock?

    > if shift_en_s = '1' then


    The following statement must be done before the rest. While simulators may
    execute them in order, synthesized logic tends to execute them all at the
    same time.

    > bcd_value := bcd_value(22 downto 0) & ser_out_s;
    > bcd_out_s <= bcd_value;


    Does this generate a gated clock? Can you do it in traditional synchronous
    logic form, where either the previous contents, or the contents with "0011"
    added are loaded back in? (Also with the shift_en_s enable.)

    > if bcd_value(3 downto 0) >= "0101" then
    > bcd_value(3 downto 0) := bcd_value(3 downto 0) + "0011";
    > end if;


    (snip)

    Gated clocks are especially hard in FPGA's.

    -- glen
    Glen Herrmannsfeldt, Jul 31, 2003
    #3
  4. Glen Herrmannsfeldt wrote:

    > Does the following generate a gated clock?
    >> if shift_en_s = '1' then


    Not if it follows the line

    elsif rising_edge(clk) then

    in a synchronous process.

    It's the process template that
    gives you a synchronous clock, not
    any single sequential statement.

    > The following statement must be done before the rest. While simulators may
    > execute them in order, synthesized logic tends to execute them all at the
    > same time.
    >
    >
    >> bcd_value := bcd_value(22 downto 0) & ser_out_s;
    >> bcd_out_s <= bcd_value;


    Actually, the synth will give you a netlist that simulates
    the same as that code, executed in order.

    Sequential statements execute in zero sim time.
    The only delay is for rising_edge(clk).

    Your code is a hardware specification that can only
    be completely understood in the context of simulation. There is
    usually no one-to-one correspondence between code statements
    and the synthesis netlist components.

    > Does this generate a gated clock? Can you do it in traditional synchronous
    > logic form, where either the previous contents, or the contents with "0011"
    > added are loaded back in? (Also with the shift_en_s enable.)
    >
    >
    >> if bcd_value(3 downto 0) >= "0101" then
    >> bcd_value(3 downto 0) := bcd_value(3 downto 0) + "0011";
    >> end if;


    This synthesizes nothing unless bcd_value is assigned
    directly or indirectly to an entity port.

    If this assignment occurs within a synchronous process,
    the output will be registered by clk.

    > Gated clocks are especially hard in FPGA's.


    If you stick to the synchronous process template, you
    will never have one to worry about.

    -- Mike Treseler
    Mike Treseler, Jul 31, 2003
    #4
  5. Glen Herrmannsfeldt

    FE Guest

    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=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" <> wrote in message
    news:IlGVa.3393$...
    > 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" <> wrote in message
    > news:GLFVa.9117$cF.3056@rwcrnsc53...
    > >
    > > "Glen Herrmannsfeldt" <> wrote in message
    > > news:MzFVa.9078$cF.2637@rwcrnsc53...
    > > >
    > > > "Jason Berringer" <> wrote in message
    > > > news:kJCVa.3413$...
    > > > > 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
    > >
    > >

    >
    >
    FE, Aug 1, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul Leventis

    Re: binary to BCD assistance

    Paul Leventis, Jul 31, 2003, in forum: VHDL
    Replies:
    4
    Views:
    4,165
    jeppe
    Mar 26, 2008
  2. Fangs
    Replies:
    3
    Views:
    9,760
    darshana
    Oct 26, 2008
  3. Yama
    Replies:
    3
    Views:
    1,322
    Dave Pollum
    Jun 9, 2006
  4. NA

    Binary to BCD in VHDL

    NA, May 23, 2007, in forum: VHDL
    Replies:
    3
    Views:
    5,269
  5. gina
    Replies:
    0
    Views:
    895
Loading...

Share This Page