Author Topic: 16 bit to 4 digit 7 segment decoder  (Read 15420 times)

0 Members and 1 Guest are viewing this topic.

Online Benta

  • Super Contributor
  • ***
  • Posts: 6420
  • Country: de
Re: 16 bit to 4 digit 7 segment decoder
« Reply #25 on: December 20, 2019, 05:39:37 pm »
To generate the 4-bit to 7-segment decoding, the simplest solution is simply a 16 x 8 array. Each byte is the segment assignments, and is addressed by the 4-bit input. This should be simple to implement in a CPLD.

 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #26 on: December 20, 2019, 06:27:36 pm »
Have not taken the time to analyze what went wrong here...

I think the difference is that the VHDL equations determine when a segment should be off rather than on.

Here is annotated equations that make this clearer...
Code: [Select]
seg_a_out     = !(  !hex_in_a_3_ & !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_   0001 1
                 #  !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_   0100 4
                 #   hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_   1011 B
                 #   hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_)  1101 D

seg_b_out     = !(  !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_   0101 5
                 #                  hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_   X110 6 E
                 #   hex_in_a_3_ &                 hex_in_a_1_ &  hex_in_a_0_   1X11 B F
                 #   hex_in_a_3_ &  hex_in_a_2_ &                !hex_in_a_0_)  11X0 C E

seg_c_out     = !(  !hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_   0010 2
                 #   hex_in_a_3_ &  hex_in_a_2_ &                !hex_in_a_0_   11X0 C E
                 #   hex_in_a_3_ &  hex_in_a_2_ &  hex_in_a_1_               )  111X E F

seg_d_out     = !(  !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_   0100 4
                 #                 !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_   X001 1 9
                 #                  hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_   X111 7 F
                 #   hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_)  1010 A

seg_e_out     = !(  !hex_in_a_3_ &                                hex_in_a_0_   0XX1 1 3 5 7
                 #                 !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_   X001 1 9
                 #  !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_               )  010X 4 5

seg_f_out     = !(  !hex_in_a_3_ & !hex_in_a_2_ &                 hex_in_a_0_   00X1 1 3
                 #  !hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_                  001X 2 3
                 #  !hex_in_a_3_ &                 hex_in_a_1_ &  hex_in_a_0_   0X11 3 7
                 #   hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_)  1101 D

seg_g_out     = !(  !hex_in_a_3_ & !hex_in_a_2_ & !hex_in_a_1_                  000X 0 1
                 #  !hex_in_a_3_ &  hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_   0111 7
                 #   hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_)  1100 C
« Last Edit: December 20, 2019, 06:30:58 pm by oPossum »
 

Offline obiwanjacobiTopic starter

  • Super Contributor
  • ***
  • Posts: 1013
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: 16 bit to 4 digit 7 segment decoder
« Reply #27 on: December 20, 2019, 07:25:20 pm »
Yeah, your code is totally understandable. I initially removed all the inverts (!) of the output assignments because I thought you may have needed outputs to go low to activate. When I saw the result and took another closer look at the equations it became clear pretty quick.

I did not analyse my first version equations...

To generate the 4-bit to 7-segment decoding, the simplest solution is simply a 16 x 8 array. Each byte is the segment assignments, and is addressed by the 4-bit input. This should be simple to implement in a CPLD.

Times 4 digits and add multiplexing for the common cathode display module...
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Online Benta

  • Super Contributor
  • ***
  • Posts: 6420
  • Country: de
Re: 16 bit to 4 digit 7 segment decoder
« Reply #28 on: December 20, 2019, 07:52:16 pm »

To generate the 4-bit to 7-segment decoding, the simplest solution is simply a 16 x 8 array. Each byte is the segment assignments, and is addressed by the 4-bit input. This should be simple to implement in a CPLD.

Times 4 digits and add multiplexing for the common cathode display module...

No! You still don't understand. You only need to do the 4 -> 7 once. The multiplexing is done before the segment decoding.

16 bits ->  split to 4 x 4 bits. A 4-bit section (eg, digit #0) is fed to the 4 -> 7 decoder and from there to the display anodes. At the same time digit #0 (the common cathode) is selected. Repeat through digits #0...#3

Got it?

« Last Edit: December 20, 2019, 08:01:38 pm by Benta »
 

Offline obiwanjacobiTopic starter

  • Super Contributor
  • ***
  • Posts: 1013
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: 16 bit to 4 digit 7 segment decoder
« Reply #29 on: December 20, 2019, 08:09:19 pm »
I think I got it. And that is what we've been talking about all along...?  :-//

If you take a look at my code for the 2 digit decoder I try to select the set of 4 bits to go into the 4-bit to 7-seg decoder TABLE based on the FF state (is digit #1 or digit #2 active?)

That is what you are saying is it not? Feed each set of 4-bits (out of the 16 bits total) into the decoder to get the correct segment outputs. In addition to that I also need to active-low the common cathode digit pin for the digit we're currently decoding...
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline jmelson

  • Super Contributor
  • ***
  • Posts: 2851
  • Country: us
Re: 16 bit to 4 digit 7 segment decoder
« Reply #30 on: December 20, 2019, 08:10:54 pm »

Meantime I remembered 5V cpld's like the Xilinx XC9572XL. Not too expensive and should be a one chip solution...
The obsolete 9500 series is 5V power and signals.  The 9500XL series is 3.3 V power, and TTL-compatible logic levels, 5V
tolerant.  (Just to set the record straight.)

Jon
 
The following users thanked this post: obiwanjacobi

Offline obiwanjacobiTopic starter

  • Super Contributor
  • ***
  • Posts: 1013
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: 16 bit to 4 digit 7 segment decoder
« Reply #31 on: December 20, 2019, 08:45:24 pm »

Meantime I remembered 5V cpld's like the Xilinx XC9572XL. Not too expensive and should be a one chip solution...
The obsolete 9500 series is 5V power and signals.  The 9500XL series is 3.3 V power, and TTL-compatible logic levels, 5V
tolerant.  (Just to set the record straight.)

Jon

Yes thank you. I did notice that when I opened up the datasheet. It does have 5V tolerant pins but its supply is max 4V. That's when I realized...
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Online Benta

  • Super Contributor
  • ***
  • Posts: 6420
  • Country: de
Re: 16 bit to 4 digit 7 segment decoder
« Reply #32 on: December 20, 2019, 10:20:57 pm »
This is what I'm talking about. Super simple to implement in a CPLD.

"D" is digit = common cathode, "S" = segments

"A" and "B" are binary inputs from a 2-bit counter/oscillator.



« Last Edit: December 20, 2019, 10:23:28 pm by Benta »
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #33 on: December 21, 2019, 02:02:03 am »
Some VHDL for 4 digit 16 bit muxed. Fits in a Lattice LSI1016.

Code: [Select]
entity hex_decode_16 is

port(
clk:       in  std_logic;
reset:     in  std_logic;
hex_in_a:  in  std_logic_vector ( 3 downto 0 );
hex_in_b:  in  std_logic_vector ( 3 downto 0 );
hex_in_c:  in  std_logic_vector ( 3 downto 0 );
hex_in_d:  in  std_logic_vector ( 3 downto 0 );
seg_a_out: out std_logic;
seg_b_out: out std_logic;
seg_c_out: out std_logic;
seg_d_out: out std_logic;
seg_e_out: out std_logic;
seg_f_out: out std_logic;
seg_g_out: out std_logic;
dig_1_out: out std_logic;
dig_2_out: out std_logic;
dig_3_out: out std_logic;
dig_4_out: out std_logic);

end;

architecture Hex_decode_16 of hex_decode_16 is

signal digit: std_logic_vector(3 downto 0);
signal hex_in: std_logic_vector(3 downto 0);
signal segments: std_logic_vector (6 downto 0);

begin
process (clk, reset, hex_in_a, hex_in_b, hex_in_c, hex_in_d)
begin
if rising_edge(clk) then
if reset = '0' then
digit <= "0001";
else
digit <= digit(2) & digit(1) & digit(0) & digit(3);
end if;
end if;

case digit is
when "0001" => hex_in <= hex_in_a;
when "0010" => hex_in <= hex_in_b;
when "0100" => hex_in <= hex_in_c;
when "1000" => hex_in <= hex_in_d;
when others => hex_in <= "0000";
end case;

case hex_in is
when "0000" => segments <= "1111110";
when "0001" => segments <= "0110000";
when "0010" => segments <= "1101101";
when "0011" => segments <= "1111001";
when "0100" => segments <= "0110011";
when "0101" => segments <= "1011011";
when "0110" => segments <= "1011111";
when "0111" => segments <= "1110000";
when "1000" => segments <= "1111111";
when "1001" => segments <= "1110011";
when "1010" => segments <= "1110111";
when "1011" => segments <= "0011111";
when "1100" => segments <= "1001110";
when "1101" => segments <= "0111101";
when "1110" => segments <= "1001111";
when "1111" => segments <= "1000111";
end case;

(seg_a_out, seg_b_out, seg_c_out, seg_d_out, seg_e_out, seg_f_out, seg_g_out) <= segments;

(dig_4_out, dig_3_out, dig_2_out, dig_1_out) <= digit;

end process;

end Hex_decode_16;
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #34 on: December 22, 2019, 02:23:07 am »
Yes, I would need to use the OE of the GALs. But I would like to program the multiplexer FF inside GAL/GALs as well. Then you'll end up with almost two identical GALs... I would use an extra input to sync up the second GAL with the first (have a couple of free inputs).

I wanted to put the counter in the GAL but couldn't think of a way to do it and also have digit select outputs. There just weren't enough pins. After thinking about it some more I came up with this...



Master
Code: [Select]
entity hex_decode_master is

port(
clk:        in  std_logic;
hex_in_a:   in  std_logic_vector ( 3 downto 0 );
hex_in_b:   in  std_logic_vector ( 3 downto 0 );
seg_a_out:  out std_logic;
seg_b_out:  out std_logic;
seg_c_out:  out std_logic;
seg_d_out:  out std_logic;
seg_e_out:  out std_logic;
seg_f_out:  out std_logic;
seg_g_out:  out std_logic;
dig_c0_out: out std_logic;
dig_c1_out: out std_logic;
dig_0_out:  out std_logic);

attribute LOC: string;
attribute LOC of clk:       signal is "1";
attribute LOC of hex_in_a:  signal is "5 4 3 2";
attribute LOC of hex_in_b:  signal is "9 8 7 6";
-- 10
-- 11
-- Gnd 12

-- 13
attribute LOC of dig_0_out:  signal is "14";
attribute LOC of dig_c0_out: signal is "15";
attribute LOC of seg_a_out:  signal is "16";
attribute LOC of seg_b_out:  signal is "17";
attribute LOC of seg_c_out:  signal is "18";
attribute LOC of seg_d_out:  signal is "19";
attribute LOC of seg_e_out:  signal is "20";
attribute LOC of seg_f_out:  signal is "21";
attribute LOC of seg_g_out:  signal is "22";
attribute LOC of dig_c1_out: signal is "23";
-- Vcc 24

end;

architecture Hex_decode_master of hex_decode_master is

signal digit: std_logic_vector(1 downto 0);
signal hex_in: std_logic_vector(3 downto 0);
signal segments: std_logic_vector (6 downto 0);

begin
process (clk, hex_in_a, hex_in_b)
begin
if rising_edge(clk) then
digit <= digit + 1;
end if;

if digit(0) = '0' then
hex_in <= hex_in_a;
else
hex_in <= hex_in_b;
end if;

case hex_in is
when "0000" => segments <= "1111110";
when "0001" => segments <= "0110000";
when "0010" => segments <= "1101101";
when "0011" => segments <= "1111001";
when "0100" => segments <= "0110011";
when "0101" => segments <= "1011011";
when "0110" => segments <= "1011111";
when "0111" => segments <= "1110000";
when "1000" => segments <= "1111111";
when "1001" => segments <= "1110011";
when "1010" => segments <= "1110111";
when "1011" => segments <= "0011111";
when "1100" => segments <= "1001110";
when "1101" => segments <= "0111101";
when "1110" => segments <= "1001111";
when "1111" => segments <= "1000111";
end case;

if digit(1) = '1' then
(seg_a_out, seg_b_out, seg_c_out, seg_d_out, seg_e_out, seg_f_out, seg_g_out) <= segments;
else
seg_a_out <= 'Z';
seg_b_out <= 'Z';
seg_c_out <= 'Z';
seg_d_out <= 'Z';
seg_e_out <= 'Z';
seg_f_out <= 'Z';
seg_g_out <= 'Z';
end if;

(dig_c1_out, dig_c0_out) <= digit;

dig_0_out <= digit(1) and not digit(0);

end process;

end Hex_decode_master;

Slave
Code: [Select]
entity hex_decode_slave is

port(
hex_in_a:  in  std_logic_vector ( 3 downto 0 );
hex_in_b:  in  std_logic_vector ( 3 downto 0 );
dig_c0_in: in  std_logic;
dig_c1_in: in  std_logic;
seg_a_out: out std_logic;
seg_b_out: out std_logic;
seg_c_out: out std_logic;
seg_d_out: out std_logic;
seg_e_out: out std_logic;
seg_f_out: out std_logic;
seg_g_out: out std_logic;
dig_3_out: out std_logic;
dig_4_out: out std_logic);

attribute LOC: string;
attribute LOC of hex_in_a:  signal is "5 4 3 2";
attribute LOC of hex_in_b:  signal is "9 8 7 6";
attribute LOC of dig_c0_in: signal is "10";
attribute LOC of dig_c1_in: signal is "11";
-- Gnd 12

-- 13
-- 14
attribute LOC of dig_3_out: signal is "15";
attribute LOC of seg_a_out: signal is "16";
attribute LOC of seg_b_out: signal is "17";
attribute LOC of seg_c_out: signal is "18";
attribute LOC of seg_d_out: signal is "19";
attribute LOC of seg_e_out: signal is "20";
attribute LOC of seg_f_out: signal is "21";
attribute LOC of seg_g_out: signal is "22";
attribute LOC of dig_4_out: signal is "23";
-- Vcc 24

end;

architecture Hex_decode_slave of hex_decode_slave is

signal hex_in: std_logic_vector(3 downto 0);
signal segments: std_logic_vector (6 downto 0);

begin
process (dig_c0_in, dig_c1_in, hex_in_a, hex_in_b)
begin
if dig_c0_in = '0' then
hex_in <= hex_in_a;
else
hex_in <= hex_in_b;
end if;

case hex_in is
when "0000" => segments <= "1111110";
when "0001" => segments <= "0110000";
when "0010" => segments <= "1101101";
when "0011" => segments <= "1111001";
when "0100" => segments <= "0110011";
when "0101" => segments <= "1011011";
when "0110" => segments <= "1011111";
when "0111" => segments <= "1110000";
when "1000" => segments <= "1111111";
when "1001" => segments <= "1110011";
when "1010" => segments <= "1110111";
when "1011" => segments <= "0011111";
when "1100" => segments <= "1001110";
when "1101" => segments <= "0111101";
when "1110" => segments <= "1001111";
when "1111" => segments <= "1000111";
end case;

if dig_c1_in = '0' then
(seg_a_out, seg_b_out, seg_c_out, seg_d_out, seg_e_out, seg_f_out, seg_g_out) <= segments;
else
seg_a_out <= 'Z';
seg_b_out <= 'Z';
seg_c_out <= 'Z';
seg_d_out <= 'Z';
seg_e_out <= 'Z';
seg_f_out <= 'Z';
seg_g_out <= 'Z';
end if;

dig_3_out <= not dig_c0_in and not dig_c1_in;
dig_4_out <= not dig_c0_in and dig_c1_in;

end process;

end Hex_decode_slave;
« Last Edit: December 22, 2019, 02:32:37 am by oPossum »
 

Online edavid

  • Super Contributor
  • ***
  • Posts: 3464
  • Country: us
Re: 16 bit to 4 digit 7 segment decoder
« Reply #35 on: December 22, 2019, 03:32:49 am »
I think the PROM approach looks pretty good sort of OK compared to GALs:

GAL: 2X 22V10 (SDIP24) + MOSFETS + clock

PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16)
PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16) + 74HC138 (DIP16)
« Last Edit: December 22, 2019, 05:23:42 pm by edavid »
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #36 on: December 22, 2019, 06:18:36 am »
PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16)

How would the cathodes be driven?
 

Online edavid

  • Super Contributor
  • ***
  • Posts: 3464
  • Country: us
Re: 16 bit to 4 digit 7 segment decoder
« Reply #37 on: December 22, 2019, 05:22:34 pm »
PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16)

How would the cathodes be driven?

Oops, what was I thinking  |O
You would also need a 74HC138 or similar.
(Or 29F400 + 74HC04 + 74HC74, but I don't like that as much.)
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15797
  • Country: fr
Re: 16 bit to 4 digit 7 segment decoder
« Reply #38 on: December 22, 2019, 05:55:31 pm »
You can actually do the same with a larger EEPROM/Flash: a 128Kx16 (I saw you can find Flash parallel 128Kx16 chips for about $1 from Microchip for instance), driving 2 digits at a time instead of one. Then the multiplexing signal would need to be only one bit as above, and you can implement the multiplexing the exact same way with just one additional chip.

Sure, unless you're very against using an MCU, this will be your simplest bet here. Don't bother using extra interface chips IMO. You can easily find MCUs with enough IOs for very cheap (and you could actually add additional interfaces in it apart from the parallel data for reusing it in other settings...)

The display unit has its segments connected across the 4 digits, so I cannot use a 16-bit lookup table output. I need to multiplex its common cathodes for each digit.

Then the following arrangement would do it:

* Use the same 128Kx16 Flash chip (eg.: SST39LF200A-55-4C-EKE, ~ $1) Use a 256Kx16 Flash/EPROM/EEPROM chip (eg.: SST39LF400A-55-4C-EKE, ~ $1.50);
* Same address input: your 16 data bits, plus 2 bits for the digit index;
* Use the data output as such: 7 bits for the segments, 4 bits for the digit select (others bits can be ignored);
* Use an additional 4060 as an oscillator for the multiplexing + use two of its counter output for the digit index (to the Flash address).

Done?

The only thing is if you need to latch the input data, I think you'll need an additional chip...?

(Clearly the MCU approach or small FPGA such as iCE40 would be more flexible and would require just one chip, but if you want to go the more "discrete" path...)
« Last Edit: December 22, 2019, 07:06:58 pm by SiliconWizard »
 

Offline PA0PBZ

  • Super Contributor
  • ***
  • Posts: 5259
  • Country: nl
Re: 16 bit to 4 digit 7 segment decoder
« Reply #39 on: December 22, 2019, 06:42:21 pm »
* Use the same 128Kx16 Flash chip (eg.: SST39LF200A-55-4C-EKE, ~ $1);
* Same address input: your 16 data bits, plus 2 bits for the digit index;
* Use the data output as such: 7 bits for the segments, 4 bits for the digit select (others bits can be ignored);
* Use an additional 4060 as an oscillator for the multiplexing + use two of its counter output for the digit index (to the Flash address).

Since you already have the digit index why do you need a digit select output? That way you only need an 8 bit chip.
Keyboard error: Press F1 to continue.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15797
  • Country: fr
Re: 16 bit to 4 digit 7 segment decoder
« Reply #40 on: December 22, 2019, 07:04:32 pm »
* Use the same 128Kx16 Flash chip (eg.: SST39LF200A-55-4C-EKE, ~ $1);
* Same address input: your 16 data bits, plus 2 bits for the digit index;
* Use the data output as such: 7 bits for the segments, 4 bits for the digit select (others bits can be ignored);
* Use an additional 4060 as an oscillator for the multiplexing + use two of its counter output for the digit index (to the Flash address).

Since you already have the digit index why do you need a digit select output? That way you only need an 8 bit chip.

The "digit index" is just a 2-bit binary count. The digit select output is 1-of-many select output. The former is easy to generate from the 4060 and only requires 2 more bits of address.
The 4-bit digit select output can directly be connected to each of the 4 digits' cathode (or maybe via a transistor, check output current.)
 

Offline PA0PBZ

  • Super Contributor
  • ***
  • Posts: 5259
  • Country: nl
Re: 16 bit to 4 digit 7 segment decoder
« Reply #41 on: December 22, 2019, 07:34:05 pm »
The "digit index" is just a 2-bit binary count. The digit select output is 1-of-many select output. The former is easy to generate from the 4060 and only requires 2 more bits of address.
The 4-bit digit select output can directly be connected to each of the 4 digits' cathode (or maybe via a transistor, check output current.)

Ah yes, you are correct.
Keyboard error: Press F1 to continue.
 

Online Benta

  • Super Contributor
  • ***
  • Posts: 6420
  • Country: de
Re: 16 bit to 4 digit 7 segment decoder
« Reply #42 on: December 22, 2019, 07:52:22 pm »
You can actually do the same with a larger EEPROM/Flash: a 128Kx16 (I saw you can find Flash parallel 128Kx16 chips for about $1 from Microchip for instance), driving 2 digits at a time instead of one. Then the multiplexing signal would need to be only one bit as above, and you can implement the multiplexing the exact same way with just one additional chip.

Sure, unless you're very against using an MCU, this will be your simplest bet here. Don't bother using extra interface chips IMO. You can easily find MCUs with enough IOs for very cheap (and you could actually add additional interfaces in it apart from the parallel data for reusing it in other settings...)

The display unit has its segments connected across the 4 digits, so I cannot use a 16-bit lookup table output. I need to multiplex its common cathodes for each digit.

Then the following arrangement would do it:

* Use the same 128Kx16 Flash chip (eg.: SST39LF200A-55-4C-EKE, ~ $1) Use a 256Kx16 Flash/EPROM/EEPROM chip (eg.: SST39LF400A-55-4C-EKE, ~ $1.50);
* Same address input: your 16 data bits, plus 2 bits for the digit index;
* Use the data output as such: 7 bits for the segments, 4 bits for the digit select (others bits can be ignored);
* Use an additional 4060 as an oscillator for the multiplexing + use two of its counter output for the digit index (to the Flash address).

Done?

The only thing is if you need to latch the input data, I think you'll need an additional chip...?

(Clearly the MCU approach or small FPGA such as iCE40 would be more flexible and would require just one chip, but if you want to go the more "discrete" path...)

4 Mb of storage to drive a 4-digit, 7-segment display? Wow, that's what I call "Brute Force"!
Especially as my post #32 shows how easy it is.

 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: 16 bit to 4 digit 7 segment decoder
« Reply #43 on: December 22, 2019, 08:37:08 pm »
How about a $1 blue pill? It's got plenty of 5V tolerant gpios: http://duckduckgo.com/?q=blue+pill+pinout&iax=images&ia=images

The further a society drifts from truth, the more it will hate those who speak it.
 

Offline obiwanjacobiTopic starter

  • Super Contributor
  • ***
  • Posts: 1013
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: 16 bit to 4 digit 7 segment decoder
« Reply #44 on: December 22, 2019, 09:06:48 pm »
BluePill: I need around 30 IO (16 bits 7/8 segements and 4 digit cathodes and possibly a latch, reset, oe that sort of thing). I don't see enough 5V pins on there.


Meanwhile I have tried to understand the code (boolean equations) I initially copied from @oPossom (never copy code you don't understand):

Code: [Select]
        case hex_in is
            when "0000" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '0';
            when "0001" => seg_a <= '0'; seg_b <= '1'; seg_c <= '1'; seg_d <= '0'; seg_e <= '0'; seg_f <= '0'; seg_g <= '0';
            when "0010" => seg_a <= '1'; seg_b <= '1'; seg_c <= '0'; seg_d <= '1'; seg_e <= '1'; seg_f <= '0'; seg_g <= '1';
            when "0011" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '1'; seg_e <= '0'; seg_f <= '0'; seg_g <= '1';
            when "0100" => seg_a <= '0'; seg_b <= '1'; seg_c <= '1'; seg_d <= '0'; seg_e <= '0'; seg_f <= '1'; seg_g <= '1';
            when "0101" => seg_a <= '1'; seg_b <= '0'; seg_c <= '1'; seg_d <= '1'; seg_e <= '0'; seg_f <= '1'; seg_g <= '1';
            when "0110" => seg_a <= '1'; seg_b <= '0'; seg_c <= '1'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            when "0111" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '0'; seg_e <= '0'; seg_f <= '0'; seg_g <= '0';
            when "1000" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            when "1001" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '0'; seg_e <= '0'; seg_f <= '1'; seg_g <= '1';
            when "1010" => seg_a <= '1'; seg_b <= '1'; seg_c <= '1'; seg_d <= '0'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            when "1011" => seg_a <= '0'; seg_b <= '0'; seg_c <= '1'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            when "1100" => seg_a <= '1'; seg_b <= '0'; seg_c <= '0'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '0';
            when "1101" => seg_a <= '0'; seg_b <= '1'; seg_c <= '1'; seg_d <= '1'; seg_e <= '1'; seg_f <= '0'; seg_g <= '1';
            when "1110" => seg_a <= '1'; seg_b <= '0'; seg_c <= '0'; seg_d <= '1'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            when "1111" => seg_a <= '1'; seg_b <= '0'; seg_c <= '0'; seg_d <= '0'; seg_e <= '1'; seg_f <= '1'; seg_g <= '1';
            --when others => seg_a <= '0'; seg_b <= '0'; seg_c <= '0'; seg_d <= '0'; seg_e <= '0'; seg_f <= '0'; seg_g <= '0';
        end case;


Boolean equations
Code: [Select]
seg_a_out     = !(   !mux &  hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_ 
                 #   !mux &  hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #   !mux & !hex_in_a_3_ & !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #   !mux & !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_
                 #    mux &  hex_in_b_3_ & !hex_in_b_2_ &  hex_in_b_1_ &  hex_in_b_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_
                 #    mux & !hex_in_b_3_ & !hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_
                 #    mux & !hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ & !hex_in_b_0_ );

seg_b_out     = !(   !mux &  hex_in_a_3_ &  hex_in_a_2_ &                !hex_in_a_0_
                 #   !mux &  hex_in_a_3_ &                 hex_in_a_1_ &  hex_in_a_0_
                 #   !mux & !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #   !mux &                 hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ &                !hex_in_b_0_
                 #    mux &  hex_in_b_3_ &                 hex_in_b_1_ &  hex_in_b_0_
                 #    mux & !hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_
                 #    mux &                 hex_in_b_2_ &  hex_in_b_1_ & !hex_in_b_0_ );

seg_c_out     = !(   !mux &  hex_in_a_3_ &  hex_in_a_2_ &                !hex_in_a_0_
                 #   !mux &  hex_in_a_3_ &  hex_in_a_2_ &  hex_in_a_1_
                 #   !mux & !hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ &                !hex_in_b_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ &  hex_in_b_1_
                 #    mux & !hex_in_b_3_ & !hex_in_b_2_ &  hex_in_b_1_ & !hex_in_b_0_ );

seg_d_out     = !(   !mux &                 hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_
                 #   !mux &                !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #   !mux &  hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_
                 #   !mux & !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_
                 #    mux &                 hex_in_b_2_ &  hex_in_b_1_ &  hex_in_b_0_
                 #    mux &                !hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_
                 #    mux &  hex_in_b_3_ & !hex_in_b_2_ &  hex_in_b_1_ & !hex_in_b_0_
                 #    mux & !hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ & !hex_in_b_0_ );

seg_e_out     = !(   !mux & !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_
                 #   !mux & !hex_in_a_3_ &                                hex_in_a_0_
                 #   !mux &                !hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #    mux & !hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_
                 #    mux & !hex_in_b_3_ &                                hex_in_b_0_
                 #    mux &                !hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_ );

seg_f_out     = !(   !mux & !hex_in_a_3_ &                 hex_in_a_1_ &  hex_in_a_0_
                 #   !mux & !hex_in_a_3_ & !hex_in_a_2_ &  hex_in_a_1_
                 #   !mux & !hex_in_a_3_ & !hex_in_a_2_ &                 hex_in_a_0_
                 #   !mux &  hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_
                 #    mux & !hex_in_b_3_ &                 hex_in_b_1_ &  hex_in_b_0_
                 #    mux & !hex_in_b_3_ & !hex_in_b_2_ &  hex_in_b_1_
                 #    mux & !hex_in_b_3_ & !hex_in_b_2_ &                 hex_in_b_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ &  hex_in_b_0_ );

seg_g_out     = !(   !mux & !hex_in_a_3_ & !hex_in_a_2_ & !hex_in_a_1_
                 #   !mux & !hex_in_a_3_ &  hex_in_a_2_ &  hex_in_a_1_ &  hex_in_a_0_
                 #   !mux &  hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ & !hex_in_a_0_
                 #    mux & !hex_in_b_3_ & !hex_in_b_2_ & !hex_in_b_1_
                 #    mux & !hex_in_b_3_ &  hex_in_b_2_ &  hex_in_b_1_ &  hex_in_b_0_
                 #    mux &  hex_in_b_3_ &  hex_in_b_2_ & !hex_in_b_1_ & !hex_in_b_0_ );


While I get that testing for when the segments are off is cheaper (less pterms) I do not see how each segment is defined with max 4 terms (the others are for the other digit an have the same logic in them). For instance b'0001 would have 5 segments that are off - not 4.

Is there some boolean reduction technique being used here?  :-//
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5170
  • Country: ro
  • .
Re: 16 bit to 4 digit 7 segment decoder
« Reply #45 on: December 22, 2019, 09:27:30 pm »
All this hassle over a few 7 segment digits.

Just get digits with common anode, then use a led driver.

For example
1 digit common anode:  https://www.digikey.com/product-detail/en/inolux/INND-TS40RAB/1830-1152-ND/7604988
2 digits (1 anode per digit) :  https://www.digikey.com/product-detail/en/lite-on-inc/LTD-6410G/160-1924-5-ND/3199123

LCSC has them for 10-15 cents per digit, here's some examples:

1. 0.56" https://lcsc.com/product-detail/Led-Segment-Display_Made-in-China-FJ5161BH_C8092.html
2. 0.36" https://lcsc.com/product-detail/Led-Segment-Display_Made-in-China-FJ3161BH_C10690.html
3. 0.80" https://lcsc.com/product-detail/Others_OASIS-TOS-3124DMG-9B4_C325438.html

4. 2 digit (2 anodes + 8 cathodes) https://lcsc.com/product-detail/Led-Segment-Display_ARKLED-Wuxi-ARK-Tech-Elec-SN430281N_C182258.html

Use an 8 channel or 16 channel led driver  and power 1-2 digits at any time directly from your microcontroller (the output pins have enough power for 10-20mA per pin)

LCSC has them for 5 cents each, or 2 cents if you buy 1000: https://lcsc.com/product-detail/LED-Drivers_Shenzhen-Sunmoon-Micro-SM74HC595D_C93838.html

There's also 10 cent led driver chips which can control directly 4 digits (4 anodes, 8 cathodes) : https://lcsc.com/product-detail/LED-Drivers_TM-Shenzhen-Titan-Micro-Elec-TM1650_C44444.html

Here's 4 digit 7segment common anode, 50 cents each or 30 cents each if you buy 100: https://lcsc.com/product-detail/Led-Segment-Display_Made-in-China-4Bit0-56Inch-red-digital-Led-Super-bright_C10713.html

 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #46 on: December 22, 2019, 10:40:34 pm »
Is there some boolean reduction technique being used here?  :-//

Yes, that is one of the advantages of using VHDL. I am using the free Lattice ispLEVER software that targets all the older Lattice GALs and CPLDs. It puts to boolean equations in the log file.

An example...
Code: [Select]
seg_b_out     = !(  !hex_in_a_3_ &  hex_in_a_2_ & !hex_in_a_1_ &  hex_in_a_0_   0101 5
                 #                  hex_in_a_2_ &  hex_in_a_1_ & !hex_in_a_0_   X110 6 E
                 #   hex_in_a_3_ &                 hex_in_a_1_ &  hex_in_a_0_   1X11 B F
                 #   hex_in_a_3_ &  hex_in_a_2_ &                !hex_in_a_0_)  11X0 C E

Handles 5, 6, B, C, E and F. Six digits with 4 OR gate inputs.

See reply 26 for all the others.
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1472
  • Country: us
  • Very dangerous - may attack at any time
Re: 16 bit to 4 digit 7 segment decoder
« Reply #47 on: December 22, 2019, 10:43:33 pm »
PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16)

How would the cathodes be driven?

Oops, what was I thinking  |O
You would also need a 74HC138 or similar.
(Or 29F400 + 74HC04 + 74HC74, but I don't like that as much.)

If directly driving the cathodes is acceptable, then the GAL solution requires only one MOSFET. It may be possible to put the oscillator in the GAL. I don't know if there is enough hysteresis on the inputs for that to work.

 

Offline obiwanjacobiTopic starter

  • Super Contributor
  • ***
  • Posts: 1013
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: 16 bit to 4 digit 7 segment decoder
« Reply #48 on: December 23, 2019, 03:48:14 pm »
See reply 26 for all the others.

Totally missed that  :palm: Thanx!

Very clever indeed. I think I'll take a look at that software you're using if only to do the crunching.
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline Peabody

  • Super Contributor
  • ***
  • Posts: 2247
  • Country: us
Re: 16 bit to 4 digit 7 segment decoder
« Reply #49 on: December 23, 2019, 03:53:26 pm »
Well here's a non-GAL option that should work with the Atmega328P 28-pin DIP package.  You would use two HC573 transparent latch chips to capture the 16-bit address bus.  Their outputs would be ganged inputs to the 328P, with the latches' /OE pins selecting which one is active.  Processor pins needed would be the 8 data lines, one latch enable, and two /OE lines, for a total of 11.  On the 7-segment side you would multiplex by segment instead of by digit, and use a single HC4017 to drive the displays.  For four digits, that would require 5 I/O pins - one for each common cathode, and one clock pin for the HC4017.  So that's a total of 16 I/O pins.

An additional benefit of multiplexing by segment is that since only one segment line is driven at a time, the maximum number of segments driven at any time is 4 instead of 8.  That means that if the displays are even moderately efficient, an HC4017 output can probably source a segment line directly without a transistor, and in fact you only need one resistor on each CC line instead of one resistor on each segment line.

Edit:  It appears the ATTiny261 would also work.  It's a 20-pin processor with 16 I/O pins.  And there's an ATTinyCore avialable for the Arduino IDE that includes support for the 261.  For a 3.3V system, the TI MSP430G2553 would be perfect, programmed with Energia, which is a port of the Arduino IDE for MSP430.

Details of this multiplexing method can be found here (there's also a video link there):

https://github.com/gbhug5a/7-Segment-Displays-Multiplex-by-Segment
« Last Edit: December 23, 2019, 06:41:19 pm by Peabody »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf