16 bit to 4 digit 7 segment decoder - Page 1
Forum section: electronics / projects

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 08:27:08 am
content: I have a (couple of) 4 digit 7 segment display module (NSB3881) and want to use it to plug into data and address buses of hobby projects to display bus values. The 7seg unit is common cathode and has all the segment lines (a-g/dp) connected over all 4 digits.I want to make a self-contained module with a 0.1" header that can be plugged into breadboards (5V logic).So I started to try to program a 2-digit version into a GAL22V10 (winCupl) but the segment mapping table generated too many product terms.My other thought was to use a cheap micro (preferably Atmel/AVR - don't know PIC and don't have the programmer for it) to read the bus signals and output the 7seg data for each digit. It would need 16 (bus data) + 8 (a-g/dp) + 4 (digit common cathodes) = 28 IO pins. (would like a reset and an optional latch too => 30 IO pins).Then I thought that perhaps there is a(nother) clever way to solve this problem and came here for inspiration.Suggestions?

author: ChristofferB
author_rank: Frequent Contributor
timestamp: December 19, 2019, 10:38:26 am
content: The simplest (and oldschoolest) way of making a logic look up table like that is using Eproms or Eeproms. You'll need an eprom per segment though.--chris

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 10:48:13 am
content: Quote from: ChristofferB on December 19, 2019, 10:38:26 amOuch. I know this method and would like to avoid it. I would also need logic to multiplex the 4 digits.I want to keep the chip count down and the module as small as possible.Meantime I remembered 5V cpld's like the Xilinx XC9572XL (*). Not too expensive and should be a one chip solution...*) Edit: this is a 3V3 version! Seethis postfor the correct info.

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: December 19, 2019, 11:32:55 am
content: Youtuber Ben Eater uses an arduino to do the dirty work. Get one with enough I/O pins.@ 10m 55s

author: Buriedcode
author_rank: Super Contributor
timestamp: December 19, 2019, 04:13:56 pm
content: You could use a 40-pin Arduino, like the MajorCore or MightyCore. Atmega8515 isn't that expensive, and has 35 IO. Only suggesting Arduino because it'll be slightly quicker to develop with, but if you're already set up with AVRs then might as well go bare metal.

author: Benta
author_rank: Super Contributor
timestamp: December 19, 2019, 04:25:01 pm
content: No reason to make it so complicated, it's a multiplexed display with 7+1(dp) segment lines and 4 common lines. You only need to do the 4-bit to 7-segment decoding once.However, you do need to build a small state machine to do the multiplexing. Basically just a decoded 2-bit counter with 4 outputs.

author: Peabody
author_rank: Super Contributor
timestamp: December 19, 2019, 04:32:41 pm
content: So you're going to display the bus states in hex, and they will change state slowly enough that you can make sense of the display in real time? You must have a very slow clock.There are BCD to 7-segment decoders, but I don't know of one that does binary to 7-segment. And even if you find one, you still have the multiplexing issue to deal with.In the Arduino world, I think you would need something like a Mega to get that many I/O pins. But perhaps you could use shift registers to reduce the pin count.This looks to be a pretty challenging project unless you use some kind of programmable logic for it. I wonder if it might make more sense to use two 8-bit buffers to directly drive 16 LEDs divided into groups of 4, one group for each nibble.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 04:39:14 pm
content: Quote from: Benta on December 19, 2019, 04:25:01 pmExactly this.But how to make it as small as possible? A 40-pin MCU (DIP) does not sound small.I am leaning toward a 5V CPLD at this point - I need (roughly) about 3-times the capacity of a 22V10.(bare metal AVR is no problem)Edit: I need about 20 pins to interface with the bus (16-bit + power + 2 spare - like latch)So a 40-pin MCU could just fit if I use a single row header. The display module itself has 16 0.1" pins.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 19, 2019, 04:53:08 pm
content: Quote from: obiwanjacobi on December 19, 2019, 08:27:08 amUse a MCP23017 to read the bus?

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 19, 2019, 05:02:16 pm
content: This would be a simple job for a CPLD/small FPGA, or even for an MCU.If you want a ready-made integrated solution, you can consider the very famous TIL311 displays, hard to find these days, awfully expensive.You also have the MC14495 which can still be found in some shops - awfully expensive as well.If you have access to EEPROMs/Flash chips and would prefer to use them instead of CPLDs or FPGAs, you can always write the conversion tables inside. For instance, you could use one per 8 bit of data (thus controlling 2 hex digits): this would only require a 512x8 memory (the address would be your 8 bits of data, plus a digit index bit, the data would be driving your segments, and it would be a multiplexing display.) Will require an extra multiplexing clock signal. Doing the same with only one chip for 16 bits would require 18 bits of address - thus a 256Kx8 memory, and a small 2-bit counter (for the 4 digits, whereas for only 2 digits, all you need is a clock). Still doable though, as 256Kx8 flash chips can be had for relatively cheap these days, and a 2-bit counter would be dead easy to implement with one simple logic IC.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 05:02:39 pm
content: Quote from: Peabody on December 19, 2019, 04:32:41 pmYes it will be a slow clock - its for debugging only. I also want an extra latch pin on there so I can use it to capture values based on specific conditions (which I can program into a GAL if needed).The registers with leds are useful, sure. But for address- and data buses I think in hex values. I will make that a module as well with the same pinout so I can swap them out if needed. I have led-bars and a couple of hundred 3mm leds in several colors. That is not the problem.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 05:07:40 pm
content: Quote from: SiliconWizard on December 19, 2019, 05:02:16 pmYes, CPLD and MCU seem the most feasible options at this time.TIL311's are too expensive indeed - I have a few but they're in use. I really wanted to used these NSB3881 displays I had laying around as a cheap alternative.I know about using an EPROM to do a lookup table but with all the support logic to multiplex 4 digits (and perhaps an internal clock / NE555) it gets pretty big. I was looking for a way to shrink that down.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 05:17:31 pm
content: Quote from: GeorgeOfTheJungle on December 19, 2019, 04:53:08 pm(had to look up the part - so I may not understand how it operates...)As a shift register and read it with a (small) MCU to do the I2C and drive the 7seg leds?Yes, could work. 2 chips would not be ideal but it does bring down the width of the module...The small MCU could be an ATtiny with at least 8+4 outputs (in addition to the I2C interface)....

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 19, 2019, 05:26:33 pm
content: Quote from: obiwanjacobi on December 19, 2019, 05:17:31 pmExactly, that's the idea.

author: David Hess
author_rank: Super Contributor
timestamp: December 19, 2019, 05:38:58 pm
content: Requiring 16 bits of binary input on the microcontroller really hurts the pin count. What I would at least consider is using a pair of external 8 bit parallel-in serial-out shift registers so the 16 bits of binary data can be latched and then read in serially which will only require 3 pins instead of 16 pins. The 74165, in whatever logic family you need, is commonly used for this function.This also allows the input latches to be remotely located and the word width is easily expandable. One strobe simultaneously latches every input even with multiple 8 bit latches so discontinuity is less of a problem.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 19, 2019, 05:47:26 pm
content: Quote from: obiwanjacobi on December 19, 2019, 05:07:40 pmThat's why I suggested going for two-digit pairs. You'd just need to duplicate it to get your 16 bits. The multiplexing would only require a single clock, and an inverter - which you can design around a 2-gate schmitt trigger inverter such as the 74LVC2G14 for instance: one inverter for the clock, the other to toggle between the two digits.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.This would be for the "vintage approach".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...)

author: Benta
author_rank: Super Contributor
timestamp: December 19, 2019, 05:48:20 pm
content: You need to partition this correctly. My suggestion would be two parts operating independently/asynchronously from each other:1: the bus capture part. I 've no idea of the signals you want to read, but it's output should be a static 16-bit state, IOW a "bus capture register".2: the display part which does the 4-bit -> 7-segment decoding and multiplexing. This part would be constantly scanning the 16-bit value from the "bus capture register".If the 16-bit value changes quickly, you might experience a bit of "ghosting" in the display. If this is a problem, you'll need an extra 16-bit latch at the input of the display part.This is just a suggestion on the "logic architecture" (not the implementation), but I'm certain a CPLD could do the job perfectly.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 19, 2019, 06:43:19 pm
content: Quote from: SiliconWizard on December 19, 2019, 05:47:26 pmThe 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.Quote from: Benta on December 19, 2019, 05:48:20 pmI don't see how this will be a problem in practice. I will use it as a debug aid where the clock speeds will be human-readably slow. Or I will add (hardware or software) logic to detect a specific circumstance that will trigger a capture, which will be displayed.Attached is a picture of the display module together with a 40-pin DIP (the Z80 was on top of the pile) to give an impression of the physical dimensions.

author: ebclr
author_rank: Super Contributor
timestamp: December 19, 2019, 07:28:18 pm
content: Do you really need to read static address, because a display will only do that?I guess is a better option to buy a DSLlogic or any other logic analyzer, you will get the same thing but dynamicIf for some special application, you really need that, a PIC, STM 8051 or even Arduino will do that very easily with the help of a display driver like LIKE TM1638 , Assuming will be for a static use since you can't see on high speed

author: oPossum
author_rank: Super Contributor
timestamp: December 19, 2019, 11:09:16 pm
content: Quote from: obiwanjacobi on December 19, 2019, 08:27:08 amI have been working on a similar project. I chose to use a 16V8 GAL for two multiplexed 7 seven segment displays. Code is in VHDL and fits. I haven't yet built and tested this so there is a chance it doesn't work.VHDLCode:entity hex_to_seven_seg_mux isport(mux: 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 );end;architecture Hex_to_seven_seg_mux of hex_to_seven_seg_mux issignal polarity: std_logic := '1';signal hex_in: std_logic_vector(3 downto 0);signal seg_a: std_logic;signal seg_b: std_logic;signal seg_c: std_logic;signal seg_d: std_logic;signal seg_e: std_logic;signal seg_f: std_logic;signal seg_g: std_logic;beginprocess (mux, hex_in_a, hex_in_b, polarity)beginif mux = '0' thenhex_in <= hex_in_a;elsehex_in <= hex_in_b;end if;case hex_in iswhen "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;if polarity = '1' thenseg_a_out <= seg_a;seg_b_out <= seg_b;seg_c_out <= seg_c;seg_d_out <= seg_d;seg_e_out <= seg_e;seg_f_out <= seg_f;seg_g_out <= seg_g;elseseg_a_out <= not seg_a;seg_b_out <= not seg_b;seg_c_out <= not seg_c;seg_d_out <= not seg_d;seg_e_out <= not seg_e;seg_f_out <= not seg_f;seg_g_out <= not seg_g;end if;end process;end Hex_to_seven_seg_mux;Boolean equationsCode: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_ );Schematic attached.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 07:26:49 am
content: That is awesome!I have to see why mine is so different (made with WinCupl) - I'm on a different computer now.I had a 22V10 and also had the multiplexer in there. I could see the at several (seg) outputs I exceeded the max number of product terms.But I do not think I can make it work for a 16-bit bus. I would need 2 chips and some way of syncing them up.----I think -based on ebay prices- a single 40-pin ATMega8515 is the cheapest as it stand now. It would also be the simplest construction/wiring.

author: oPossum
author_rank: Super Contributor
timestamp: December 20, 2019, 10:52:35 am
content: Quote from: obiwanjacobi on December 20, 2019, 07:26:49 amI am not suggesting this is a good way, but I think it would work.Code:entity hex_to_7_seg_multi isport(hex_in_a: in std_logic_vector ( 3 downto 0 );hex_in_b: in std_logic_vector ( 3 downto 0 );enable_a: in std_logic;enable_b: 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);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 enable_a: signal is "10";attribute LOC of enable_b: signal is "11";-- Gnd 12attribute LOC of seg_a_out: signal is "15";attribute LOC of seg_b_out: signal is "16";attribute LOC of seg_c_out: signal is "17";attribute LOC of seg_d_out: signal is "18";attribute LOC of seg_e_out: signal is "19";attribute LOC of seg_f_out: signal is "20";attribute LOC of seg_g_out: signal is "21";-- Vcc 24end;architecture Hex_to_7_seg_multi of hex_to_7_seg_multi issignal polarity: std_logic := '0';signal hex_in: std_logic_vector(3 downto 0);signal seg_a: std_logic;signal seg_b: std_logic;signal seg_c: std_logic;signal seg_d: std_logic;signal seg_e: std_logic;signal seg_f: std_logic;signal seg_g: std_logic;signal enabled: std_logic;ATTRIBUTE SYN_KEEP : integer;ATTRIBUTE SYN_KEEP OF enabled : SIGNAL IS 1;ATTRIBUTE OPT : string;ATTRIBUTE OPT OF enabled: SIGNAL IS "KEEP";beginprocess (enable_a, enable_b, hex_in_a, hex_in_b, polarity, enabled)beginif enable_b = '1' thenhex_in <= hex_in_b;elsehex_in <= hex_in_a;end if;case hex_in iswhen "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';end case;enabled <= enable_a or enable_b;if enabled = '1' thenif polarity = '1' thenseg_a_out <= seg_a;seg_b_out <= seg_b;seg_c_out <= seg_c;seg_d_out <= seg_d;seg_e_out <= seg_e;seg_f_out <= seg_f;seg_g_out <= seg_g;elseseg_a_out <= not seg_a;seg_b_out <= not seg_b;seg_c_out <= not seg_c;seg_d_out <= not seg_d;seg_e_out <= not seg_e;seg_f_out <= not seg_f;seg_g_out <= not seg_g;end if;elseseg_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;end process;end Hex_to_7_seg_multi;

author: tggzzz
author_rank: Super Contributor
timestamp: December 20, 2019, 11:06:46 am
content: Quote from: obiwanjacobi on December 20, 2019, 07:26:49 amTo minimise pins, check out the concepts behind "charlieplexing".

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 12:00:41 pm
content: Quote from: oPossum on December 20, 2019, 10:52:35 amYes, 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 have to look at you solution in greater detail and compare it to my design (that was too big). Perhaps I can find a way to slim it down...?---Quote from: tggzzz on December 20, 2019, 11:06:46 amPost #1Quote from: obiwanjacobi on December 19, 2019, 08:27:08 amI do not know how to charlieplex common cathode segements...(I am not intimate with the finer details of charlieplexing)

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 04:15:57 pm
content: @oPossumI have tried your (first) example and copied the boolean expressions and it works fine.I think my initial CUPL code was too 'abstract' for the compiler to optimize well...This code:Code:Name 2-Digit 7-Segment Decoder;PartNo 2D7SDecoder-01;Date 18-12-2019;Revision 01;Designer Marc Jacobi;Company Canned Bytes;Assembly unknown;Location unknown;Device g22v10;/*Format j ;*//** input pins **/PIN 1 = CLK;PIN 2 = D0;PIN 3 = D1;PIN 4 = D2;PIN 5 = D3;PIN 6 = D4;PIN 7 = D5;PIN 8 = D6;PIN 9 = D7;/** output pins **/PIN 14 = a;PIN 15 = b;PIN 16 = c;PIN 17 = d;PIN 18 = e;PIN 19 = f;PIN 20 = g;PIN 21 = dp;PIN 22 = n1;PIN 23 = n2;/* not used */n1.ar = 'b'0;n1.sp = 'b'0;n1.d = !n1;n2 = !n1;dec0 = (D0 & n1) # (D4 & !n1);dec1 = (D1 & n1) # (D5 & !n1);dec2 = (D2 & n1) # (D6 & !n1);dec3 = (D3 & n1) # (D7 & !n1);FIELD decode = [dec3, dec2, dec1, dec0];FIELD output = [dp, g, f, e, d, c, b, a];TABLE decode => output{0 => 'b'00111111;1 => 'b'00000110;2 => 'b'01011011;3 => 'b'01001111;4 => 'b'01100110;5 => 'b'01101101;6 => 'b'01111101;7 => 'b'00000111;8 => 'b'01111111;9 => 'b'01101111;A => 'b'11110111;B => 'b'11111100;C => 'b'10111001;D => 'b'11011110;E => 'b'11111011;F => 'b'11110001;}resulted in these equationsCode:a =>D4 & D5 & D6 & D7 & !n1# !D4 & D7 & !n1# D0 & D1 & D2 & D3 & n1# !D0 & D3 & n1# !D0 & !D2 & !D3 & n1# !D4 & !D6 & !D7 & !n1# D0 & D1 & !D3 & n1# D4 & D5 & !D7 & !n1# !D0 & D1 & D2 & !D3 & n1# D0 & !D1 & D2 & !D3 & n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1b =>!D4 & D5 & D7 & !n1# !D0 & D1 & D3 & n1# !D0 & !D1 & !D3 & n1# !D2 & !D3 & n1# !D4 & !D5 & !D7 & !n1# !D6 & !D7 & !n1# D0 & D1 & !D3 & n1# D4 & D5 & !D7 & !n1# D0 & !D1 & D2 & D3 & n1# D4 & !D5 & D6 & D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1c =>!D4 & D5 & !D6 & D7 & !n1# !D0 & D1 & !D2 & D3 & n1# D0 & D1 & !D2 & n1# !D1 & !D3 & n1# D4 & D5 & !D6 & !n1# !D5 & !D6 & !D7 & !n1# !D4 & !D5 & D6 & !D7 & !n1# D0 & D1 & !D3 & n1# D4 & D5 & !D7 & !n1# D0 & !D1 & D2 & D3 & n1# !D0 & D1 & D2 & !D3 & n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1d =>!D4 & D5 & D6 & D7 & !n1# !D0 & D1 & D2 & D3 & n1# !D0 & !D2 & !D3 & n1# D0 & D1 & !D2 & n1# !D0 & !D1 & D2 & D3 & n1# !D4 & !D6 & !D7 & !n1# D4 & D5 & !D6 & !n1# !D4 & !D5 & D6 & D7 & !n1# D0 & !D1 & D2 & D3 & n1# !D0 & D1 & D2 & !D3 & n1# D0 & !D1 & D2 & !D3 & n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1dec0 =>D0 & n1# D4 & !n1dec1 =>D1 & n1# D5 & !n1dec2 =>D2 & n1# D6 & !n1dec3 =>D3 & n1# D7 & !n1decode =>dec3 , dec2 , dec1 , dec0dp =>D5 & D7 & !n1# D1 & D3 & n1# !D0 & !D1 & D2 & D3 & n1# !D4 & !D5 & D6 & D7 & !n1# D0 & !D1 & D2 & D3 & n1# D4 & !D5 & D6 & D7 & !n1e =>D5 & D7 & !n1# !D4 & D7 & !n1# D1 & D3 & n1# !D0 & D3 & n1# !D0 & !D2 & !D3 & n1# !D4 & !D6 & !D7 & !n1# D0 & !D1 & D2 & D3 & n1# !D0 & D1 & D2 & !D3 & n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1f =>D5 & D7 & !n1# !D4 & D7 & !n1# D1 & D3 & n1# !D0 & D3 & n1# !D0 & !D1 & !D3 & n1# !D4 & !D5 & !D7 & !n1# !D0 & D1 & D2 & !D3 & n1# D0 & !D1 & D2 & !D3 & n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1g =>D5 & D7 & !n1# !D4 & D5 & !D6 & !D7 & !n1# D1 & D3 & n1# !D0 & !D1 & D2 & !D3 & n1# D1 & !D2 & !D3 & n1# D4 & D5 & !D6 & !n1# !D4 & !D5 & D6 & !D7 & !n1# D0 & !D1 & D2 & D3 & n1# !D0 & D1 & D2 & !D3 & n1# D0 & !D1 & D2 & !D3 & n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D1 & !D2 & D3 & n1# !D5 & !D6 & D7 & !n1n1.d =>D5 & D7 & !n1# !D4 & !D5 & D6 & D7 & !n1# !D6 & !D7 & !n1# !D4 & !D5 & D6 & !D7 & !n1# D4 & D5 & !D7 & !n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D5 & !D6 & D7 & !n1n1.ar =>0n1.sp =>0n2 =>D5 & D7 & !n1# !D4 & !D5 & D6 & D7 & !n1# !D6 & !D7 & !n1# !D4 & !D5 & D6 & !D7 & !n1# D4 & D5 & !D7 & !n1# D4 & !D5 & D6 & D7 & !n1# !D4 & D5 & D6 & !D7 & !n1# D4 & !D5 & D6 & !D7 & !n1# !D5 & !D6 & D7 & !n1output =>dp , g , f , e , d , c , b , aHave not taken the time to analyze what went wrong here...

author: Benta
author_rank: Super Contributor
timestamp: December 20, 2019, 05:39:37 pm
content: 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.

author: oPossum
author_rank: Super Contributor
timestamp: December 20, 2019, 06:27:36 pm
content: Quote from: obiwanjacobi on December 20, 2019, 04:15:57 pmI 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: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 Dseg_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 Eseg_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 Fseg_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 Aseg_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 5seg_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 Dseg_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

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 07:25:20 pm
content: 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...Quote from: Benta on December 20, 2019, 05:39:37 pmTimes 4 digits and add multiplexing for the common cathode display module...

author: Benta
author_rank: Super Contributor
timestamp: December 20, 2019, 07:52:16 pm
content: Quote from: obiwanjacobi on December 20, 2019, 07:25:20 pmNo! You still don't understand. You only need to do the 4 -> 7 once. The multiplexing is donebeforethe 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...#3Got it?

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 08:09:19 pm
content: 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...

author: jmelson
author_rank: Super Contributor
timestamp: December 20, 2019, 08:10:54 pm
content: Quote from: obiwanjacobi on December 19, 2019, 10:48:13 amThe obsolete 9500 series is 5V power and signals. The 9500XL series is 3.3 V power, and TTL-compatible logic levels, 5Vtolerant. (Just to set the record straight.)Jon

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 20, 2019, 08:45:24 pm
content: Quote from: jmelson on December 20, 2019, 08:10:54 pmYes 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...

author: Benta
author_rank: Super Contributor
timestamp: December 20, 2019, 10:20:57 pm
content: 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.

author: oPossum
author_rank: Super Contributor
timestamp: December 21, 2019, 02:02:03 am
content: Some VHDL for 4 digit 16 bit muxed. Fits in a Lattice LSI1016.Code:entity hex_decode_16 isport(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 issignal digit: std_logic_vector(3 downto 0);signal hex_in: std_logic_vector(3 downto 0);signal segments: std_logic_vector (6 downto 0);beginprocess (clk, reset, hex_in_a, hex_in_b, hex_in_c, hex_in_d)beginif rising_edge(clk) thenif reset = '0' thendigit <= "0001";elsedigit <= digit(2) & digit(1) & digit(0) & digit(3);end if;end if;case digit iswhen "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 iswhen "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;

author: oPossum
author_rank: Super Contributor
timestamp: December 22, 2019, 02:23:07 am
content: Quote from: obiwanjacobi on December 20, 2019, 12:00:41 pmI 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...MasterCode:entity hex_decode_master isport(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-- 13attribute 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 24end;architecture Hex_decode_master of hex_decode_master issignal digit: std_logic_vector(1 downto 0);signal hex_in: std_logic_vector(3 downto 0);signal segments: std_logic_vector (6 downto 0);beginprocess (clk, hex_in_a, hex_in_b)beginif rising_edge(clk) thendigit <= digit + 1;end if;if digit(0) = '0' thenhex_in <= hex_in_a;elsehex_in <= hex_in_b;end if;case hex_in iswhen "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;elseseg_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;SlaveCode:entity hex_decode_slave isport(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-- 14attribute 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 24end;architecture Hex_decode_slave of hex_decode_slave issignal hex_in: std_logic_vector(3 downto 0);signal segments: std_logic_vector (6 downto 0);beginprocess (dig_c0_in, dig_c1_in, hex_in_a, hex_in_b)beginif dig_c0_in = '0' thenhex_in <= hex_in_a;elsehex_in <= hex_in_b;end if;case hex_in iswhen "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;elseseg_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;

author: edavid
author_rank: Super Contributor
timestamp: December 22, 2019, 03:32:49 am
content: I think the PROM approach lookspretty goodsort of OK compared to GALs:GAL: 2X 22V10 (SDIP24) + MOSFETS + clockPROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16)PROM: AT29C020 or equivalent (DIP32) + 74HC4060 (DIP16) + 74HC138 (DIP16)

author: oPossum
author_rank: Super Contributor
timestamp: December 22, 2019, 06:18:36 am
content: Quote from: edavid on December 22, 2019, 03:32:49 amHow would the cathodes be driven?

author: edavid
author_rank: Super Contributor
timestamp: December 22, 2019, 05:22:34 pm
content: Quote from: oPossum on December 22, 2019, 06:18:36 amOops, what was I thinkingYou would also need a 74HC138 or similar.(Or 29F400 + 74HC04 + 74HC74, but I don't like that as much.)

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 22, 2019, 05:55:31 pm
content: Quote from: obiwanjacobi on December 19, 2019, 06:43:19 pmThen 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...)

author: PA0PBZ
author_rank: Super Contributor
timestamp: December 22, 2019, 06:42:21 pm
content: Quote from: SiliconWizard on December 22, 2019, 05:55:31 pmSince you already have the digit index why do you need a digit select output? That way you only need an 8 bit chip.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 22, 2019, 07:04:32 pm
content: Quote from: PA0PBZ on December 22, 2019, 06:42:21 pmThe "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.)

author: PA0PBZ
author_rank: Super Contributor
timestamp: December 22, 2019, 07:34:05 pm
content: Quote from: SiliconWizard on December 22, 2019, 07:04:32 pmAh yes, you are correct.

author: Benta
author_rank: Super Contributor
timestamp: December 22, 2019, 07:52:22 pm
content: Quote from: SiliconWizard on December 22, 2019, 05:55:31 pm4 Mbof 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.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 22, 2019, 08:37:08 pm
content: 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

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 22, 2019, 09:06:48 pm
content: 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):Quote from: oPossum on December 19, 2019, 11:09:16 pmWhile 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?

author: mariush
author_rank: Super Contributor
timestamp: December 22, 2019, 09:27:30 pm
content: All this hassle over a few 7 segment digits.Just get digits with common anode, then use a led driver.For example1 digit common anode:https://www.digikey.com/product-detail/en/inolux/INND-TS40RAB/1830-1152-ND/76049882 digits (1 anode per digit) :https://www.digikey.com/product-detail/en/lite-on-inc/LTD-6410G/160-1924-5-ND/3199123LCSC 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.html2. 0.36"https://lcsc.com/product-detail/Led-Segment-Display_Made-in-China-FJ3161BH_C10690.html3. 0.80"https://lcsc.com/product-detail/Others_OASIS-TOS-3124DMG-9B4_C325438.html4. 2 digit (2 anodes + 8 cathodes)https://lcsc.com/product-detail/Led-Segment-Display_ARKLED-Wuxi-ARK-Tech-Elec-SN430281N_C182258.htmlUse 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.htmlThere'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.htmlHere'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

author: oPossum
author_rank: Super Contributor
timestamp: December 22, 2019, 10:40:34 pm
content: Quote from: obiwanjacobi on December 22, 2019, 09:06:48 pmYes, 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: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 EHandles 5, 6, B, C, E and F. Six digits with 4 OR gate inputs.See reply 26 for all the others.

author: oPossum
author_rank: Super Contributor
timestamp: December 22, 2019, 10:43:33 pm
content: Quote from: edavid on December 22, 2019, 05:22:34 pmIf 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.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 23, 2019, 03:48:14 pm
content: Quote from: oPossum on December 22, 2019, 10:40:34 pmTotally missed thatThanx!Very clever indeed. I think I'll take a look at that software you're using if only to do the crunching.

author: Peabody
author_rank: Super Contributor
timestamp: December 23, 2019, 03:53:26 pm
content: 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

author: Buriedcode
author_rank: Super Contributor
timestamp: December 23, 2019, 07:35:38 pm
content: Wow, these solutions are varied but have run away. I'm unsure of the exact restrictions, but 30 5V IO, ease of use and cost, I will stand by an Atmega8515. $2.50, has Arduino support if you're up for fast development, easily available etc.. you just need current limiting resistors for the segments and maybe transistors for the commons (but often you can just drive from the IO) and thats it. Why all the glue logic and memories?Sure you could use a CPLD, but quite a lot of the cells will be used to store your 16-bit data, plus they tend to be more expensive than an MCU (especially the 5V tolerant ones).

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 23, 2019, 09:15:02 pm
content: Quote from: Buriedcode on December 23, 2019, 07:35:38 pmA blue pill can do it as well and it's faster, smaller and only $1. Just sayin'

author: westfw
author_rank: Super Contributor
timestamp: January 04, 2020, 08:09:30 am
content: Lots of ~40pin micros are in the $1 range and could do this fine. Some in DIPs, even (Atmega4809 is currently cheaper than ATmega8515, and ATmega32as are available for about $0.75 on Aliexpress...Or two smaller microcontrollers with a serial link between them (extensible!) - it's a human-readable display, right? It doesn't need to update as fast as the inputs can change...

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 04, 2020, 09:01:09 am
content: Yep, just for debugging and verification at very low clock rates. I also want a latch signal on there as well in order to be able to capture specific bus events.I have ordered the ATmega8515 to give it a try. (waiting...)

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 26, 2020, 04:49:09 pm
content: Made a breadboard test setup and used an Arduino Uno to program the Atmega8515. Came up with something like this.Have a quick and dirty Arduino sketch that demonstrates it working.I have setup a timer interrupt to do the multiplexing and the main loop just reads in the two ports and bit-shifts it into 4 digit (volatile) variables that are used by the timer interrupt to display.I am now building a perf board to test it further and actually use it - see if I come up with more features.I made a quick PCB layout and routing and could get all traces on one sideI will put it on my github when its a little less rough...Code:const uint8_t DecoderTable_size = 17;uint8_t DecoderTable ={0b00000001,0b01111110,0b00001100,0b10110110,0b10011110,0b11001100,0b11011010,0b11111010,0b00001110,0b11111110,0b11001110,0b11101110,0b11111000,0b01110010,0b10111100,0b11110010,0b11100010,};uint8_t decode7(uint8_t value){if (value >= DecoderTable_size)return DecoderTable;return DecoderTable[value + 1];}void outputDigit4(uint8_t value, int digit){uint8_t cathode = ~(1 << digit) & 0x0F;uint8_t b = (PORTB & 0xF0);PORTD = 0;PORTB = b | cathode;PORTD = decode7(value);}// digit values that will be displayed// timer interrupt will drive 7-segconst uint8_t digitValue_size = 4;// 0-3 => left to rightvolatile uint8_t _digitValue;// what digit are we writing?volatile uint8_t _digitIndex;// called when ORC1A is reachedISR(TIMER1_COMPA_vect){outputDigit4(_digitValue, _digitIndex);if (_digitIndex < digitValue_size){_digitIndex++;}else{_digitIndex = 0;}}void setupTimer(){OCR1A = 0x1FF;TCCR1B |= 0b010; // prescaler: CS1[2:0]TCCR1B |= (1 << WGM12); // CTC modeTIMSK |= (1 << OCIE1A); // enable interrupt}void setupPorts(){// input sampling portsDDRA = 0;DDRC = 0;// 7-seg driversDDRB |= 0x0F;DDRD = 255;}void setup(){setupTimer();setupPorts();sei();}void printDigit16(uint8_t msb, uint8_t lsb){_digitValue = msb >> 4;_digitValue = msb & 0x0F;_digitValue = lsb >> 4;_digitValue = lsb & 0x0F;}void loop(){uint8_t msb = PINA;uint8_t lsb = PINC;printDigit16(msb, lsb);}int main(){setup();while (true){loop();}}

author: Benta
author_rank: Super Contributor
timestamp: January 26, 2020, 07:00:39 pm
content: Where are the common cathode drivers?

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 26, 2020, 07:33:27 pm
content: Quote from: Benta on January 26, 2020, 07:00:39 pmMisread the NSB3881 datasheet.So I will need them.Any recommendations for a logic level FET?

author: Benta
author_rank: Super Contributor
timestamp: January 26, 2020, 07:45:49 pm
content: Just use a ULN2003. It doesn't get any simpler or cheaper.

author: bson
author_rank: Unknown
timestamp: January 27, 2020, 08:27:31 pm
content: Many of the 48 pin QFP MSP430's will do this neatly, and have enough 16 bit ports to make life easy. Since it's a 16-bit processor you can stage the segment output as 16 bit data in a pattern buffer, to be output to a 16-bit port to drive the segments, and just have a DMA controller continuously scan it, possibly triggered by a timer. When the DMA gets to the end it interrupts and you restart it in the handler. Then to update the segments you write to the pattern buffer. Since each segment gets the same number of words staged in the pattern buffer this becomes simple and reliable, without potentially weird timing problems as it might if different bits in different GPIO registers are updated in sequence. Similarly on the input, a GPIO pin interrupts and you read a 16-bit I/O register. If it has changed you wake the main CPU in the interrupt handler (DMA will run in some sleep modes, and you wake it by modifying the pushed status register; TI-CCS has C macros and functions for this), save the new value (so you can detect changes), translate it to digits, convert to segment I/O words and store them to the pattern buffer, and go back to sleep.

author: edavid
author_rank: Super Contributor
timestamp: January 27, 2020, 10:15:17 pm
content: Quote from: obiwanjacobi on January 26, 2020, 07:33:27 pmWhat's your peak segment current? If it's 10mA, 70mA/digit is not all that far from the spec of 40mA per pin. It would probably work OK.

author: oPossum
author_rank: Super Contributor
timestamp: January 27, 2020, 11:54:04 pm
content: 2N7000 and 2N7002 N channel MOSFETs will work with 5 volt CMOS logic. TO-92 or SOT-23 package.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 28, 2020, 06:27:11 am
content: Quote from: bson on January 27, 2020, 08:27:31 pmI'm looking forward to your version!Quote from: edavid on January 27, 2020, 10:15:17 pmYep its 10mA per segement, but the MCU pin is only 20mA. I have it on the breadboard without cathode-driver and I wouldn't mind it being a little brighter.Quote from: oPossum on January 27, 2020, 11:54:04 pmDon't I need P-Channel here: low-side/cathode?

author: edavid
author_rank: Super Contributor
timestamp: January 28, 2020, 04:13:40 pm
content: Quote from: obiwanjacobi on January 28, 2020, 06:27:11 amOn the datasheet (http://ww1.microchip.com/downloads/en/devicedoc/doc2512.pdf), page 197, it says 40mA per pin.A modern display would be at least 10X brighter... just saying

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 28, 2020, 06:46:08 pm
content: Yes I see you're right. Wonder how I got 20mA in my head. Thanks!I have been eyeing some modern 4 digit common cathode displays...I think I'll design my PCB in such a way that both/multiple can be fitted - if its not too much trouble.

author: technix
author_rank: Super Contributor
timestamp: January 28, 2020, 07:41:34 pm
content: Maybe it is doable using just some logic chips? 74HC164 + 74HC4511 + ULN2003 + 74HCU04/74HC14 + 4x 74LVC4245. The choice of 74HCU04 versus 74HC14 depends on your clock choice, 74HCU04 for crystal and ceramic clocks, 74HC14 for RC clocks.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 28, 2020, 07:44:07 pm
content: Quote from: obiwanjacobi on January 28, 2020, 06:27:11 amNope?

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 28, 2020, 08:00:12 pm
content: Quote from: SiliconWizard on January 28, 2020, 07:44:07 pmThanks, I looked it up again.Is there a smaller ULN2003. Not 7 darlingtons but less, 4 (or 2x2)?

author: Buriedcode
author_rank: Super Contributor
timestamp: January 28, 2020, 08:59:33 pm
content: Am I missing some kind of design restriction here or do you just need something to drive the common cathodes of the segment display? Jellybean NPN transistors with base resistors will do just fine. 2N7000 will also work.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 28, 2020, 11:01:22 pm
content: Yeah frankly, you're dealing with < 100mA of current here. You can use any small NMOS directly driven by a GPIO. You can add series resistors to the gates for good measure, but even that could be done without...

author: macboy
author_rank: Super Contributor
timestamp: January 29, 2020, 05:50:15 pm
content: Quote from: obiwanjacobi on December 19, 2019, 08:27:08 amI'd say ditch the old display modules and just buy something new. For around $1 you can get a 8 digit 7-segment display which is controlled serially using a MAX7219-alike controller. Then a small cheap micro like Arduino Nano (etc) has just enough I/O for the 16 bit input and to control the display. The extra digits could be used to hold min/max values, display voltage read from an A/D pin, etc. Or use the vertical segments to display the raw bits (4 bits per 7-seg digit).

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 30, 2020, 07:26:31 am
content: Quote from: macboy on January 29, 2020, 05:50:15 pmThat may be the direction this would be going in the end. I did not fully realize how old these modules were and how much the LEDs have improved over the years. The initial idea was to use what I had and for now that will be sufficient (currently building one prototype on perf-board after trying it out on a breadboard) but when I need a couple of them I may well upgrade.The initial question was more aimed at how to condense the logic needed for a 4-bit to hex-digit decoder. For the idea was to use a GAL to do the decoding. That could also still be a nice option (a lot of people would be happy with) - have a single chip that drives one digit on 4 bits of data.Thanks guys, for sharing all your ideas.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 30, 2020, 04:45:11 pm
content: Quote from: obiwanjacobi on January 30, 2020, 07:26:31 amYup, now that you settled for using a MCU, you could "upgrade" this using either more recent LED displays or even an LCD display instead, which would reduce power consumption a lot and could allow some fancier display.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: January 31, 2020, 08:03:07 am
content: Or one of thosesexy small SPI OLED displays...

author: obiwanjacobi
author_rank: Super Contributor
timestamp: February 05, 2020, 04:19:24 pm
content: I've published my code and schematic.https://github.com/obiwanjacobi/16BitDigits8515Also finished the perf-board prototype that is working nicely.Enjoy.

author: Benta
author_rank: Super Contributor
timestamp: February 05, 2020, 07:27:38 pm
content: Quote from: obiwanjacobi on February 05, 2020, 04:19:24 pmI'm still missing the common cathode drivers...

author: TomS_
author_rank: Frequent Contributor
timestamp: February 05, 2020, 07:39:58 pm
content: Is something like a TIL311 or DIS1417 out of the question? All of the decoding is built in, and it includes the ability to latch data and blank as well, so you can use some of the control signals to ensure you get a stable display or block out anything you dont want to see.They are really nice displays to look at too.Power hungry though!