Re: binary to BCD assistance

  • Thread starter Glen Herrmannsfeldt
  • Start date
G

Glen Herrmannsfeldt

Jason Berringer said:
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
 
G

Glen Herrmannsfeldt

Glen Herrmannsfeldt said:
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
 
G

Glen Herrmannsfeldt

Jason Berringer said:
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
 
M

Mike Treseler

Glen said:
Does the following generate a gated clock?

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.

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.)

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
 
F

FE

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top