Electronics > Projects, Designs, and Technical Stuff
16 bit to 4 digit 7 segment decoder
SiliconWizard:
--- Quote from: obiwanjacobi on December 19, 2019, 05:07:40 pm ---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.
--- End quote ---
That'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...)
Benta:
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.
obiwanjacobi:
--- Quote from: SiliconWizard on December 19, 2019, 05:47:26 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...)
--- End quote ---
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.
--- Quote from: Benta on December 19, 2019, 05:48:20 pm ---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.
--- End quote ---
I 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.
ebclr:
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 dynamic
If 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
oPossum:
--- Quote from: obiwanjacobi on December 19, 2019, 08:27:08 am ---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.
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.
--- End quote ---
I 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.
VHDL
--- Code: ---entity hex_to_seven_seg_mux is
port(
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 is
signal 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;
begin
process (mux, hex_in_a, hex_in_b, polarity)
begin
if mux = '0' then
hex_in <= hex_in_a;
else
hex_in <= hex_in_b;
end if;
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;
if polarity = '1' then
seg_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;
else
seg_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;
--- End code ---
Boolean equations
--- Code: ---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_ );
--- End code ---
Schematic attached.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version