BCD counter and 7 segment LCD help.

B

bob

Hi I have installed a 6 digit 7 segment LCD on my protoboard.

I have a signal (pulses) that I want to count and then display.
I want to send the pulses to 6 cascaded BCD counters.
I will send each BCD output to a BCD to 7 segment Decoder and then out
to my LCD
I am using Xilinx webpack but there is no VHDL BCD counters or BCD to
7 segment modules in its library.

Does enyone have a example code or could they point me to a example on
the web?

A 7 segment LED driver could be converted with a phase input to toggle
the outputs for the LCD.

If there is a better way to do the same thing I would be interested.

Thanks
Martin
 
M

Mark van de Belt

bob said:
Hi I have installed a 6 digit 7 segment LCD on my protoboard.

I have a signal (pulses) that I want to count and then display.
I want to send the pulses to 6 cascaded BCD counters.
I will send each BCD output to a BCD to 7 segment Decoder and then out
to my LCD
I am using Xilinx webpack but there is no VHDL BCD counters or BCD to
7 segment modules in its library.

Does enyone have a example code or could they point me to a example on
the web?

A 7 segment LED driver could be converted with a phase input to toggle
the outputs for the LCD.

If there is a better way to do the same thing I would be interested.

Thanks
Martin

Hello Martin,

Use a look-up table if you want to create a BCD to 7 segment converter:

signal BCD_IN: std_logic_vector (3 downto 0);
signal SEG_OUT: std_logic_vector (7 downto 0);

BCD_2_7SEGM:
process(BCD_IN)
begin
case BCD_IN is
when X"0" => SEG_OUT<= "0111111";
when X"1" => SEG_OUT<= "0000110";
when X"2" => SEG_OUT<= "1011011";
when X"3" => SEG_OUT<= "1001111";
when X"4" => SEG_OUT<= "1100110";
when X"5" => SEG_OUT<= "1101101";
when X"6" => SEG_OUT<= "1111101";
when X"7" => SEG_OUT<= "0000111";
when X"8" => SEG_OUT<= "1111111";
when X"9" => SEG_OUT<= "1101111";
when others => SEG_OUT<= "0000000";
end case;
end process;

A BCD counter is probably easiest (quick and dirty) with the following code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity bcdtest is
port (
CLK : in std_logic;
COUNT_OUT : out std_logic_vector (23 downto 0));
end bcdtest;

architecture arch of bcdtest is

signal bcd_count : unsigned (23 downto 0);

begin

COUNTER:
process (CLK)
begin
if CLK'event and CLK = '1' then
if bcd_count (3 downto 0) = "1001" then
bcd_count (3 downto 0) <= (others => '0');
if bcd_count (7 downto 4) = "1001" then
bcd_count (7 downto 4) <= (others => '0');
if bcd_count (11 downto 8) = "1001" then
bcd_count (11 downto 8) <= (others => '0');
if bcd_count (15 downto 12) = "1001" then
bcd_count (15 downto 12) <= (others => '0');
if bcd_count (19 downto 16) = "1001" then
bcd_count (19 downto 16) <= (others => '0');
if bcd_count (23 downto 20) = "1001" then
bcd_count (23 downto 20) <= (others => '0');
else
bcd_count (23 downto 20) <= bcd_count (23 downto 20) + 1;
end if;
else
bcd_count (19 downto 16) <= bcd_count (19 downto 16) + 1;
end if;
else
bcd_count (15 downto 12) <= bcd_count (15 downto 12) + 1;
end if;
else
bcd_count (11 downto 8) <= bcd_count (11 downto 8) + 1;
end if;
else
bcd_count (7 downto 4) <= bcd_count (7 downto 4) + 1;
end if;
else
bcd_count (3 downto 0) <= bcd_count (3 downto 0) + 1;
end if;
end if;
end process;

COUNT_OUT <= std_logic_vector(bcd_count);

end arch;


This code will probably produce a lot of logic. there is probably a cleaner
way to generate a BCD counter, specially with more digits.
This code will create 6 adders and 24 registers (35 slices in Xilinx spartan
2E). There should be a way to use only one adder, because only one of the
digits will count, but I can't come up with that at the moment.

I hope this helps,

Mark.
 
C

Charles M. Elias

bob said:
Hi I have installed a 6 digit 7 segment LCD on my protoboard.

I have a signal (pulses) that I want to count and then display.
I want to send the pulses to 6 cascaded BCD counters.
I will send each BCD output to a BCD to 7 segment Decoder and then out
to my LCD
I am using Xilinx webpack but there is no VHDL BCD counters or BCD to
7 segment modules in its library.

Does enyone have a example code or could they point me to a example on
the web?

A 7 segment LED driver could be converted with a phase input to toggle
the outputs for the LCD.

If there is a better way to do the same thing I would be interested.

Thanks
Martin
Martin here is a decade counter and an example that cascades three of
the counters. It is quite simple to add 3 more counters. This scheme
will require no adders.

library ieee;
use ieee.std_logic_1164.all;
--------------------------------------------------------------------------------
package pkgdecade is
component decade_counter
port ( clock : in std_logic;
clear_L : in std_logic := '1'; --optional low-assertive
clear
enable : in std_logic := '1'; --enable in
en_nxt : out std_logic; --enable to next decade
DigOut : out natural range 9 downto 0 );
end component;

end pkgdecade;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.pkgdecade.all;

entity decade_counter is
port ( clock : in std_logic;
clear_L : in std_logic := '1';
enable : in std_logic := '1';
en_nxt : out std_logic;
DigOut : out natural range 9 downto 0 );
end decade_counter;


architecture behav of decade_counter is
begin
process ( clock, clear_L, enable )

variable int_count : integer range 0 to 9;

begin
if clock = '1' and clock'event then
if clear_L = '0' then
int_count := 0;
elsif enable = '1' then
if int_count = 9 then
int_count := 0;
else
int_count := int_count + 1;
end if; --int_count = 9
end if; -- clear_L = '0'
end if; --clock transition
if enable = '1' and int_count = 9 then
en_nxt <= '1';
else
en_nxt <= '0';
end if;
DigOut <= int_count;
end process;
end behav;
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.pkgdecade.all;
--------------------------------------------------------------------------------
entity DecadeChain is
port ( Cclock : in std_logic;
Cclear_L : in std_logic;
CDigit2 : out natural range 9 downto 0;
CDigit1 : out natural range 9 downto 0;
CDigit0 : out natural range 9 downto 0 );
end DecadeChain;

architecture archDecadeChain of DecadeChain is

signal en2, en1 : std_logic;

begin
Dec2 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
enable => en2,
en_nxt => open,
DigOut => CDigit2 );

Dec1 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
enable => en1,
en_nxt => en2,
DigOut => CDigit1 );

Dec0 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
en_nxt => en1,
DigOut => CDigit0 );

end archDecadeChain;
 
C

Charles M. Elias

bob said:
Hi I have installed a 6 digit 7 segment LCD on my protoboard.

I have a signal (pulses) that I want to count and then display.
I want to send the pulses to 6 cascaded BCD counters.
I will send each BCD output to a BCD to 7 segment Decoder and then out
to my LCD
I am using Xilinx webpack but there is no VHDL BCD counters or BCD to
7 segment modules in its library.

Does enyone have a example code or could they point me to a example on
the web?

A 7 segment LED driver could be converted with a phase input to toggle
the outputs for the LCD.

If there is a better way to do the same thing I would be interested.

Thanks
Martin,

Here is another version of the decade counter chain that I posted
earlier. The only difference is that the decade outputs are a subtype
of std_logic_vector instead of type natural. I thought I'd better do
this before I get a lot of flack for using an integer output instead
of a binary one. The first version would work OK, but I do like the
second version better.

Charles
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

----------------------------------------------------------------------------------


package pkgdecade is

subtype digit is std_logic_vector( 9 downto 0 );

component decade_counter
port ( clock : in std_logic;
clear_L : in std_logic := '1'; --optional low-assertive
clear
enable : in std_logic := '1'; --enable in
en_nxt : out std_logic; --enable to next decade
DigOut : out digit
);
end component;

end pkgdecade;
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.pkgdecade.all;

entity decade_counter is
port ( clock : in std_logic;
clear_L : in std_logic := '1';
enable : in std_logic := '1';
en_nxt : out std_logic;
DigOut : out digit
);
end decade_counter;


architecture behav of decade_counter is
begin
process ( clock, clear_L, enable )

variable int_count : integer range 0 to 9;

begin
if clock = '1' and clock'event then
if clear_L = '0' then
int_count := 0;
elsif enable = '1' then
if int_count = 9 then
int_count := 0;
else
int_count := int_count + 1;
end if; --int_count = 9
end if; -- clear_L = '0'
end if; --clock transition
if enable = '1' and int_count = 9 then
en_nxt <= '1';
else
en_nxt <= '0';
end if;
DigOut <= std_logic_vector(To_Unsigned( int_count, digout'length
));
end process;
end behav;
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.pkgdecade.all;
--------------------------------------------------------------------------------------
entity DecadeChain is
port ( Cclock : in std_logic;
Cclear_L : in std_logic;
CDigit2 : out digit;
CDigit1 : out digit;
CDigit0 : out digit );
end DecadeChain;

architecture archDecadeChain of DecadeChain is

signal en2, en1 : std_logic;

begin
Dec2 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
enable => en2,
en_nxt => open,
DigOut => CDigit2 );

Dec1 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
enable => en1,
en_nxt => en2,
DigOut => CDigit1 );

Dec0 : decade_counter port map ( clock => Cclock,
clear_L => Cclear_L,
en_nxt => en1,
DigOut => CDigit0 );

end archDecadeChain;
 
B

bob

Thanks
If I want to togle the outputs with a phase signal (keeps LCD from
burning) whats the best way?
Should I check if the phase input is high

if phase= '1' then
case BCD_IN is
when X"0" => SEG_OUT<= "0111111";
when X"1" => SEG_OUT<= "0000110";
when X"2" => SEG_OUT<= "1011011";
when X"3" => SEG_OUT<= "1001111";
when X"4" => SEG_OUT<= "1100110";
when X"5" => SEG_OUT<= "1101101";
when X"6" => SEG_OUT<= "1111101";
when X"7" => SEG_OUT<= "0000111";
when X"8" => SEG_OUT<= "1111111";
when X"9" => SEG_OUT<= "1101111";
when others => SEG_OUT<= "0000000";
end case;
else
case BCD_IN is
when X"0" => SEG_OUT<= "1000000";
when X"1" => SEG_OUT<= "1111001";
when X"2" => SEG_OUT<= "0100100";
when X"3" => SEG_OUT<= "0110000";
when X"4" => SEG_OUT<= "0011001";
when X"5" => SEG_OUT<= "0010010";
when X"6" => SEG_OUT<= "0000010";
when X"7" => SEG_OUT<= "1111000";
when X"8" => SEG_OUT<= "0000000";
when X"9" => SEG_OUT<= "0010000";
when others => SEG_OUT<= "1111111";
end case;

or is there a better way?
 
J

Jonathan Bromley

If I want to togle the outputs with a phase signal (keeps LCD from
burning) whats the best way?
Should I check if the phase input is high

if phase= '1' then
case BCD_IN is
when X"0" => SEG_OUT<= "0111111"; [...]
end case;
else
case BCD_IN is [...]
end case;

or is there a better way?

Yes, there's a much better way. Just write
your case statement once, creating the (non-toggled)
signal SEG_VALUE. Then XOR that signal with the
phase (backplane) signal to create the signal that
will actually drive the LCD segments, SEG_TO_LCD:

signal SEG_TO_LCD: std_logic_vector(SEG_VALUE'range);
...
SEG_TO_LCD <= SEG_VALUE when phase = '1' else not SEG_VALUE;

General rule of life: If you end up writing almost exactly
the same piece of code twice, you're probably doing it wrong.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * Perl * Tcl/Tk * Verification * Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: (e-mail address removed)
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
G

G. G. Ditzel

Is there an easy (or at least not so difficult) way to make a
"generic" version of this counter, that is, a way to especify the
number of digits to be used? In your code you used 3 digits (CDigit2,
CDigit1, CDigit0), but what if I want to use N digits?

Thank you.

Ditzel
 

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

Similar Threads


Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top