Skocz do zawartości

Prosty zegar na układzie CPLD (wyświetlacze 7-seg.)


Pomocna odpowiedź

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

(edytowany)

@atlantis86 Hej. Też zaczynałem od takiego układu. Jak chcesz to mogę ci dać schemat dla połączenia pamięci konfiguracyjnej spi  i układu jtag. Widzę że masz programator. Mam testy za sobą i wiem jak to poskładać. XC3S50A VQ100 i pamięć (M25P16) to koszt twojego CPLD.  dcf77. sprawdzałeś czy fale radiowe są w twojej okolicy jeszcze do odczytania przez odbiornik? ( to fale radiowe z Niemiec i według moich informacji i nie są dostępne globalnie, nawet nie na terenie całej Polski). Jak pokażesz kod w vhdl to może można go uprościć by routing był korzystniejszy dla twojego układu. W wielu przypadkach granicą fizyczną układów programowalnych nie jest wykorzystanie zasobów, lecz ograniczone ilości połączeń między nimi i wiem to z doświadczenia. Pozdrawiam.

 

Edytowano przez kroszkanorber
  • Lubię! 1
12 godzin temu, kroszkanorber napisał:

@atlantis86 Hej. Też zaczynałem od takiego układu. Jak chcesz to mogę ci dać schemat dla połączenia pamięci konfiguracyjnej spi  i układu jtag. Widzę że masz programator. Mam testy za sobą i wiem jak to poskładać. XC3S50A VQ100 i pamięć (M25P16) to koszt twojego CPLD.

Chętnie rzucę okiem. 🙂

12 godzin temu, kroszkanorber napisał:

dcf77. sprawdzałeś czy fale radiowe są w twojej okolicy jeszcze do odczytania przez odbiornik? ( to fale radiowe z Niemiec i według moich informacji i nie są dostępne globalnie, nawet nie na terenie całej Polski).

Tak, DCF77 wykorzystywałem już w kilku różnych projektach, w tym jednym z wykorzystaniem elementów retro. 🙂

Zasięg nie jest tutaj problemem. Ten system pracuje w niskim zakresie fal długich, które bardzo dobrze się propagują na znaczne odległości. Nadajnik obejmuje swoim zasięgiem praktycznie całą Europę i północną część Afryki. Problem leży gdzie indziej - obecnie to pasmo jest bardzo mocno zakłócane przez rozmaite zasilacze i ładowarki impulsowe. Skrajnie mało prawdopodobne jest więc odebranie poprawnej ramki za pierwszym razem - trzeba czekać. Zwykle udaje się to dopiero w nocy, bo po pierwsze wtedy na paśmie poprawiają się warunki propagacyjne, a po drugie ludzie wyłączają część siejących urządzeń. Większa jest też szansa na poprawne działanie poza miastem (mniejsze zagęszczenie źródeł zakłóceń). Do tego przed ustawieniem czasu trzeba odebrać dwie poprawne ramki pod rząd - transmisja nie zawiera żadnej sumy kontrolnej, więc tylko w ten sposób można mieć pewność, że nie ustawiamy zegara w oparciu o przypadkowe śmieci.

12 godzin temu, kroszkanorber napisał:

Jak pokażesz kod w vhdl to może można go uprościć by routing był korzystniejszy dla twojego układu. W wielu przypadkach granicą fizyczną układów programowalnych nie jest wykorzystanie zasobów, lecz ograniczone ilości połączeń między nimi i wiem to z doświadczenia. Pozdrawiam.

Możesz rzucić okiem. Kod jest TUTAJ. Zakładam, że może być nieoptymalny - jak wspominam, to był mój pierwszy (i jak to tej pory jedyny) większy projekt na CPLD/FPGA. Będę musiał jeszcze kiedyś do tego wrócić, pewnie przy okazji kolejnej konstrukcji w klimatach retro. 😉

(edytowany)

@atlantis86

image.thumb.png.133655be3bb89246f11b800fbb7e2083.png

image.thumb.png.7f8610da5ec67f56cad4419a4f295c54.png

to schemat połączeń jtag i kości spi do układu xc3s50A vq100. 
Nie analizowałem dokładnie twojego kodu. Chyba zrobiłeś równoległe dekodery bin do displ dla każdej cyfry. Można zrobić mux 4x4 z wyborem cyfr binarnie kodowanych do jednego dekodera i 4 sygnały enable dla każdego wyświetlacza np. LEDen1, LEDen2, LEDen3, LEDen4. te sygnały powinny wysterować mux dla dekodera wyświetlacza i odpowiednią cyfrę. wszystkie cyfry połączyć równolegle do wyjścia a do f. wysterować je po kolei przez tranzystor na wspólną anodę lub katodę (zależy od wyświetlacza) w częstotliwości ok200Hz. pozbędziesz się w ten sposób trzech dekoderów dla pozostałych cyfr zastępując je muxem co w konsekwencji zwolni zasoby w cpld. 
Jaki moduł DCF używasz? 

Edytowano przez kroszkanorber

@atlantis86 kod zegarka z wyświetlaczem 7 segmentowym 6 cyfr. 
mieści się w xc2c64. W twoim xc2c128 będzie miejsce na inną logikę.
Ten kod nie jest dla fpga poprawny, a cpld to przerobi bez problemów z timingiem.
Zegarek jest w stylu retro . 

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    17:59:57 02/03/2026 
-- Design Name: 
-- Module Name:    zegar - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
--    H       M       S     - a
--  _   _   _   _   _   _   - b
-- |_| |_| |_| |_| |_| |_|  - c
-- |_| |_| |_| |_| |_| |_|  - d
--                          - e
--  |   |   |   |   |   |   - f
-- dg1 dg2 dg3 dg4 dg5 dg6  - g
-- 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity zegar is
    Port ( Clk : in  STD_LOGIC; -- 32 khz
           Rst : in  STD_LOGIC;
           a : out  STD_LOGIC;
           b : out  STD_LOGIC;
           c : out  STD_LOGIC;
           d : out  STD_LOGIC;
           e : out  STD_LOGIC;
           f : out  STD_LOGIC;
           g : out  STD_LOGIC;
           dg1 : out  STD_LOGIC;
           dg2 : out  STD_LOGIC;
           dg3 : out  STD_LOGIC;
           dg4 : out  STD_LOGIC;
           dg5 : out  STD_LOGIC;
           dg6 : out  STD_LOGIC);
end zegar;

architecture Behavioral of zegar is

	signal Cnt1hz : std_logic_vector (14 downto 0);
	signal CntS9  : std_logic_vector (3 downto 0);
	signal CntS59 : std_logic_vector (2 downto 0);
	signal CntM9  : std_logic_vector (3 downto 0);
	signal CntM59 : std_logic_vector (2 downto 0);
	signal CntH9  : std_logic_vector (3 downto 0);
	signal CntH23 : std_logic_vector (1 downto 0);
	signal En1hz  : std_logic;
	signal EnS9   : std_logic;
	signal EnS59  : std_logic;
	signal EnM9   : std_logic;
	signal EnM59  : std_logic;
	signal EnH9   : std_logic;
	signal EnH23  : std_logic;
	signal Muxen  : std_logic;
	signal RstG   : std_logic;
	signal Mux    : std_logic_vector (2 downto 0);
	signal Bcd    : std_logic_vector (3 downto 0);
	signal Led    : std_logic_vector (6 downto 0);
	
begin
	
	-- generator 1hz
	process(Clk, Rst)
	begin
		if Rst = '0' then
			Cnt1hz <= (others => '0');
		elsif falling_edge(Clk) then
			if En1hz = '1' then
				Cnt1hz <= (others => '0');
			else
				Cnt1hz <= Cnt1hz + 1;
			end if;
		end if;
	end process;
	
	En1hz <= '1' when Cnt1hz = "111110011111111" else '0';
	
	-- licznik sekund jednostki
	process(En1hz, RstG)
	begin
		if RstG = '0' then
			CntS9 <= "0000";
		elsif falling_edge(En1hz) then
			if CntS9 = "1001" then
				CntS9 <= "0000";
			else
				CntS9 <= CntS9 + 1;
			end if;
		end if;
	end process;
	
	EnS9 <= CntS9(CntS9'left);
	
	-- licznik sekund dziesiątki
	process(EnS9, RstG)
	begin
		if RstG = '0' then
			CntS59 <= "000";
		elsif falling_edge(EnS9) then
			if CntS59 = "101" then
				CntS59 <= "000";
			else
				CntS59 <= CntS59 + 1;
			end if;
		end if;
	end process;
	
	EnS59 <= CntS59(CntS59'left);
	
	-- licznik minut jednostki
	process(EnS59, RstG)
	begin
		if RstG = '0' then
			CntM9 <= "0000";
		elsif falling_edge(EnS59) then
			if CntM9 = "1001" then
				CntM9 <= "0000";
			else
				CntM9 <= CntM9 + 1;
			end if;
		end if;
	end process;
	
	EnM9 <= CntM9(CntM9'left);
	
	-- licznik minut dziesiątki
	process(EnM9, RstG)
	begin
		if RstG = '0' then
			CntM59 <= "000";
		elsif falling_edge(EnM9) then
			if CntM59 = "101" then
				CntM59 <= "000";
			else
				CntM59 <= CntM59 + 1;
			end if;
		end if;
	end process;
	
	EnM59 <= CntM59(CntM59'left);
	
	-- licznik godzin jednostki
	process(EnM59, RstG)
	begin
		if RstG = '0' then
			CntH9 <= "0000";
		elsif falling_edge(EnM59) then
			if CntH9 = "1001" then
				CntH9 <= "0000";
			else
				CntH9 <= CntH9 + 1;
			end if;
		end if;
	end process;
	
	EnH9 <= CntH9(CntH9'left);
	
	-- licznik godzin dziesiątki
	process(EnH9, RstG)
	begin
		if RstG = '0' then
			CntH23 <= "00";
		elsif falling_edge(EnH9) then
			if CntH23 = "10" then
				CntH23 <= "00";
			else
				CntH23 <= CntH23 + 1;
			end if;
		end if;
	end process;
	
	-- dekoder reset 24 godziny
	EnH23 <= '0' when CntH9 = "0100" and CntH23 = "10" else '1';
	
	RstG <= Rst and EnH23;
	
	-- zegar dla Mux 256hz
	Muxen <= Cnt1hz(7);
	
	-- licznik Mux
	process(Muxen)
	begin
		if falling_edge(Muxen) then
			if Mux = "101" then
				Mux <= "000";
			else
				Mux <= Mux + 1;
			end if;
		end if;
	end process;
	
	-- wybór cyfry bcd z licznika zegara
	with Mux select
	Bcd <= "00" & CntH23 when "000",
					  CntH9  when "001",
			  '0' & CntM59 when "010",
                 CntM9  when "011",
			  '0' & CntS59 when "100",
					  CntS9  when others;
	
	-- wybór wyświetlanej cyfry
	process(Mux)
	begin
		dg1 <= '0';
		dg2 <= '0';
		dg3 <= '0';
		dg4 <= '0';
		dg5 <= '0';
		dg6 <= '0';
		case Mux is
			when "000" => dg1 <= '1';
			when "001" => dg2 <= '1';
			when "010" => dg3 <= '1';
			when "011" => dg4 <= '1';
			when "100" => dg5 <= '1';
			when others => dg6 <= '1';
		end case;
	end process;
	
	-- dekoder licby bcd do wyświetlacza 7 segmentowego
	with Bcd select
   Led <= "1111001" when "0001",   --1
          "0100100" when "0010",   --2
          "0110000" when "0011",   --3
          "0011001" when "0100",   --4
          "0010010" when "0101",   --5
          "0000010" when "0110",   --6
          "1111000" when "0111",   --7
          "0000000" when "1000",   --8
          "0010000" when "1001",   --9
          "1000000" when others;   --0
			
	-- podpięcie sygnałów do wyświetlacza 7 segmentowego
	a <= Led(0);
	b <= Led(1);
	c <= Led(2);
	d <= Led(3);
	e <= Led(4);
	f <= Led(5);
	g <= Led(6);
		
	


end Behavioral;

 

(edytowany)
16 godzin temu, kroszkanorber napisał:

to schemat połączeń jtag i kości spi do układu xc3s50A vq100. 

Dzięki. Możliwe, że wykorzystam w którymś z przyszłych projektów. 😉

16 godzin temu, kroszkanorber napisał:


Nie analizowałem dokładnie twojego kodu. Chyba zrobiłeś równoległe dekodery bin do displ dla każdej cyfry. Można zrobić mux 4x4 z wyborem cyfr binarnie kodowanych do jednego dekodera i 4 sygnały enable dla każdego wyświetlacza np. LEDen1, LEDen2, LEDen3, LEDen4. te sygnały powinny wysterować mux dla dekodera wyświetlacza i odpowiednią cyfrę. wszystkie cyfry połączyć równolegle do wyjścia a do f. wysterować je po kolei przez tranzystor na wspólną anodę lub katodę (zależy od wyświetlacza) w częstotliwości ok200Hz. pozbędziesz się w ten sposób trzech dekoderów dla pozostałych cyfr zastępując je muxem co w konsekwencji zwolni zasoby w cpld. 

Prawdę mówiąc w tym projekcie celowo postanowiłem nie korzystać z multipleksingu. Z perspektywy czasu widzę, że jego użycie pozwoliłoby oszczędzić trochę zasobów wewnątrz CPLD, zostawiając miejsce na implementację chociażby dekodowania DCF77. Jednak na tym etapie jego wprowadzenie wymagałoby też przeróbek sprzętowych, więc chyba prościej jednak będzie kupić xc2c256. 😉

Jednak dzięki za udostępnienie kodu - możliwe, że wykorzystam kiedyś w jakimś innym projekcie zegara na CPLD. 😉

16 godzin temu, kroszkanorber napisał:

Jaki moduł DCF używasz? 

Prawdę mówiąc już nie pamiętam, jakiś losowy, kupiony na Allegro parę lat temu.

Edytowano przez atlantis86

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...