VHDL 數字時鍾設計


序言

這個是我在做FPGA界的HelloWorld——數字鍾設計時隨手寫下的,再現了數字鍾設計的過程

目標分析

  1. 時鍾具有時分秒的顯示,需6個數碼管。為了減小功耗采用掃描法顯示
  2. 按鍵設置時間,需要對按鍵進行消抖
  3. 時分秒即為2個60進制計數器,一個24進制計數器。

模塊設計

綜上所述,我采用模塊化設計方法進行設計,繪制框圖如下。

  1. 時鍾分頻產生各個模塊所需頻率時鍾。
  2. 按鍵處理模塊對按鍵信號進行消抖、變長脈沖為短脈沖等處理。
  3. 時間控制模塊產生時間信號或對時間進行設置。
  4. 數碼管驅動模塊負責對時間信號BCD碼譯碼為數碼管的段碼並且掃描輸出到數碼管。
    下面對各個模塊分別詳細敘述

時鍾分頻模塊

我打算把時鍾分頻模塊做成“數控N分頻器”,通過給分頻器傳入數值N來對時鍾信號進行N分頻。得到的信號頻率為原時鍾信號的頻率/N,占空比為1/N。
稍微考慮下其他模塊所需時鍾:按鍵處理模塊100Hz ,時間控制模塊1Hz,數碼管驅動50Hz。而輸入時鍾為33.8688MHz。
我不想傳入的N數值過大,我打算先對時鍾進行兩次:第一次調用時鍾分頻模塊得到1Mhz,第二次得到1Khz。這樣N的位數為10可以滿足需求。
代碼如下

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity ClkDiv is
	port(
	clk_i:IN STD_LOGIC;
	N_i:  IN STD_LOGIC_VECTOR(9 DOWNTO 0);
	clk_o:OUT STD_LOGIC);
end ClkDiv;

architecture behavior of ClkDiv is
signal count:STD_LOGIC_VECTOR(9 DOWNTO 0):="0000000001";
signal clk_temp:STD_LOGIC:='0';
begin
	process(clk_i)
	begin
		if(clk_i'EVENT and clk_i='1')then  
			if (count=N_i)then
				count<="0000000001";
				clk_temp<='1';
			else
				count<=count+1;
				clk_temp<='0';
			end if;
		end if;
	end process;	
	clk_o<=clk_temp;
end behavior;

仿真結果如下:
2分頻:輸出信號為f/2Hz,占空比1:2

3分頻:輸出信號為f/3Hz,占空比1:3

按鍵處理模塊

去抖動根據以往的經驗,按鍵按下彈起電平會有一小段毛刺,可能會引起電路誤操作,所以要對按鍵進行消抖處理使變為干凈的矩形信號。


抖動時間一般為10ms,若采樣時間為10ms則噪聲最多采樣到一次。
對於兩級D觸發器,Q1和Q2之間有一個時間延遲效果。每一次時鍾上升沿就是對信號采樣一次,Q1保存的是最新一次的采樣Q2保存的是上一次的采樣,Q1和Q2之間有一個時間延遲,時間為時鍾周期。

對於噪聲信號只能采樣到一次,Q1*Q2的值一定為0。

對於持續時間大於時鍾周期的信號可以采樣到兩次,Q1的值和Q2的值相同,Q1*Q2為信號電平。這就是去抖原理。



代碼如下

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity JitterElimination is	
	port(
	key: IN STD_LOGIC;
	clk_i:IN STD_LOGIC;
	DLY_OUT:OUT STD_LOGIC);
	
end JitterElimination;

architecture rtl of JitterElimination is
signal D1,D2,S:STD_LOGIC;
begin
	process(clk_i)
	begin
		if (clk_i'EVENT and clk_i='1')then
			D1<=key;
			D2<=D1;
		end if;
	end process;	
	S<=D1 and D2;	
	DLY_OUT<=S;
	
end rtl;

仿真結果如下

可以看到,按鍵的抖動被消除了,但是可以看到按鍵按下電平持續時間跨過幾個時鍾周期。如果有必要可以使用微分電路把矩形波轉換為窄脈沖波,這里不需要。

數碼管驅動模塊

時分秒顯示需要2+2+2=6個數碼管,每個數碼管的顯示需要8根引腳。使用掃描方式顯示,只需要6+8=14根引腳,功耗比較低。
輸入:時間信號BCD碼有4*6=24位,用於控制掃描頻率的時鍾信號是1個輸入信號

輸出:位選信號6位,段碼8位

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity LEDScan is 
	port(
		CurTime_i:  IN STD_LOGIC_VECTOR(23 DOWNTO 0); 
		clk_i:IN STD_LOGIC;
		Position_o:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
		Section_o: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
	function convert(BCD:STD_LOGIC_VECTOR(3 DOWNTO 0)) return STD_LOGIC_VECTOR is
		variable Section: STD_LOGIC_VECTOR(7 DOWNTO 0);		
	begin
		Case BCD is
			when "0000" =>Section:="00111111"; --段碼表————————————---------------------------------------------
			when "0001" =>Section:="00000110"; --0x3f,0x06,0x5b,0x4f,0x66,												
			when "0010" =>Section:="01011011"; --0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
			when "0011" =>Section:="01001111";
			when "0100" =>Section:="01100110"; 
			
			when "0101" =>Section:="01101101";
			when "0110" =>Section:="01111101";
			when "0111" =>Section:="00000111";
			when "1000" =>Section:="01111111"; 
			when "1001"	=>Section:="01101111";
			when OTHERS =>Section:="01100110";--01110001 	 
			
--			when "0000" =>Section:="11000000"; --段碼表{0x88,0x83,0xc6,0xa1,0x86,0x8e}----------------
--			when "0001" =>Section:="11111001"; --0xc0,0xf9,0xa4,0xb0,0x99,												
--			when "0010" =>Section:="10100100"; --0x92,0x82,0xf8, 0x80,0x90,
--			when "0011" =>Section:="10110000";
--			when "0100" =>Section:="10011001"; 
--			
--			when "0101" =>Section:="10010010";
--			when "0110" =>Section:="10000010";
--			when "0111" =>Section:="11111000";
--			when "1000" =>Section:="10000000"; 
--			when "1001"	=>Section:="10010000";
--			when OTHERS =>Section:="10001110"; 			
		end case;
		return Section;
	end convert;
end LEDScan;



architecture behaviour of LEDScan is 
	signal CurTimeTemp:STD_LOGIC_VECTOR(23 DOWNTO 0):="000000000000000000000000";
	signal SectionTemp,Section0,Section1,Section2,Section3,Section4,Section5:  STD_LOGIC_VECTOR(7 DOWNTO 0):="00111111";--此處應為0的段碼,數碼管共陰數碼管-----------------------------------------------------------------------		
	signal Position	:integer :=5;
begin 

	process(clk_i) 
	begin
		if (clk_i'EVENT and clk_i='1') then	
			
			CurTimeTemp<=CurTime_i;
			Section0<=convert(CurTimeTemp(3 DOWNTO 0));
			Section1<=convert(CurTimeTemp(7 DOWNTO 4));
			Section2<=convert(CurTimeTemp(11 DOWNTO 8));  
			Section3<=convert(CurTimeTemp(15 DOWNTO 12));
			Section4<=convert(CurTimeTemp(19 DOWNTO 16));
			Section5<=convert(CurTimeTemp(23 DOWNTO 20));			
			
			if (Position=5)then
				Position<=0;
			else
				Position<=Position+1;
			end if;	 
			
			case Position is 
				when 0 =>Section_o<=Section0;Position_o<="000001";
				when 1 =>Section_o<=Section1;Position_o<="000010";
				when 2 =>Section_o<='1'&Section2(6 downto 0);Position_o<="000100"; --添加小數點
				when 3 =>Section_o<=Section3;Position_o<="001000";		
				when 4 =>Section_o<='1'&Section4(6 downto 0);Position_o<="010000";
				when 5 =>Section_o<=Section5;Position_o<="100000";
				when OTHERS=>NULL;
			end case;
		end if;	
	end process;
	
	

end behaviour;

仿真結果如下圖所示

我們可以看到在當前時間為23:59:59的情況下Section5里面放的是2的段碼,Section4里面放的是3的段碼,Section3里面放的是5的段碼
在時鍾的作用下,Position_o依次選中個位,Section_o輸出的是選中位置的段碼。

時間控制模塊

我想用兩個按鍵分別設置分鍾,時鍾數值。分鍾增1的條件是按鍵按下或者秒計數器進位,時鍾增1的條件是按鍵2按下或者分鍾計數器進位。這樣可以在不破壞正常運行狀態的情況下,用按鍵對分、時進行加1操作(設置),滿足了功能又沒有增加設計的復雜度。
最后將計數器的值翻譯為BCD碼,連接到一起形成24位BCD碼。

輸入:按鍵1和按鍵2、1Hz時間脈沖
輸出:24位BCD碼

N進制計數器



library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity Counter is	  
	port(
	CountClk:in STD_LOGIC; 
	N: in STD_LOGIC_VECTOR(4 downto 0); 
	count:out STD_LOGIC_VECTOR(4 downto 0);
	Cout:out STD_LOGIC);
end Counter;


architecture behav of Counter is	 
signal count_temp: STD_LOGIC_VECTOR(4 downto 0):="00000"; 
signal CoutTemp:STD_LOGIC:='0';
begin		 
	process(CountClk) 
	begin	
		if (CountClk'EVENT and CountClk='1')then
			count_temp<=count_temp+1;
			CoutTemp<='0';
			if (count_temp>=N)then
				count_temp<="00000";	
				CoutTemp<='1';
			end if;
		end if;
	end process;
	Cout<=CoutTemp;
	count<=count_temp;
end behav;

控制模塊


library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;


entity Contrl is 
		port(
			MinKey_i:IN STD_LOGIC;
			HourKey_i:IN STD_LOGIC;
			clk_i:IN STD_LOGIC;
			CurrentTimeBCD_o: OUT STD_LOGIC_VECTOR(23 downto 0));
end Contrl;

architecture behavior of Contrl is
	signal h: integer range 0 to 23 := 0;	-- 秒鍾個位
	signal m: integer range 0 to 59 := 0;	-- 秒鍾個位
	signal s: integer range 0 to 59 := 0;	-- 秒鍾個位
	signal s1: integer range 0 to 9 := 0;	-- 秒鍾個位
	signal s2: integer range 0 to 5 := 0;	-- 秒鍾百位
	signal m1: integer range 0 to 9 := 0;	-- 分鍾個位
	signal m2: integer range 0 to 5 := 0;	-- 分鍾百位
	signal h1: integer range 0 to 9 := 0;	-- 時鍾個位
	signal h2: integer range 0 to 2 := 0;	-- 時鍾百位	
	signal CurrentTimeBCD :  STD_LOGIC_VECTOR(23 downto 0):="000000000000000000000000";	
	constant N9:STD_LOGIC_VECTOR(4 downto 0):="01001"; 
	constant N5:STD_LOGIC_VECTOR(4 downto 0):="00101"; 
	constant N1:STD_LOGIC_VECTOR(4 downto 0):="00001";
	constant N23:STD_LOGIC_VECTOR(4 downto 0):="10111";
	signal CountS1:STD_LOGIC_VECTOR(4 downto 0):="00000";  
	signal CountS2:STD_LOGIC_VECTOR(4 downto 0):="00000"; 
	signal CountH:STD_LOGIC_VECTOR(4 downto 0):="00000";
	signal CountM1:STD_LOGIC_VECTOR(4 downto 0):="00000";
	signal CountM2:STD_LOGIC_VECTOR(4 downto 0):="00000";
	signal CountH1:STD_LOGIC_VECTOR(4 downto 0):="00000";
	signal CountH2:STD_LOGIC_VECTOR(4 downto 0):="00000";
	
	
	signal KeyMTemp:STD_LOGIC:='1';
	signal KeyHTemp:STD_LOGIC:='1';
	
	signal CoutS1:STD_LOGIC:='0'; 
	signal CoutS2:STD_LOGIC:='0';  
	signal CoutM1:STD_LOGIC:='0'; 
	signal CoutM2:STD_LOGIC:='0';
	
	signal CoutH:STD_LOGIC:='0'; 
	signal CoutH1:STD_LOGIC:='0'; 
	signal CoutH2:STD_LOGIC:='0';
	component Counter is 
		port(
			CountClk:in STD_LOGIC; 
			N: in STD_LOGIC_VECTOR(4 downto 0); 
			count:out STD_LOGIC_VECTOR(4 downto 0);
			Cout:out STD_LOGIC);
	end component; 	
	
	
begin
	KeyMTemp<=CoutS2 xor (not MinKey_i);
	KeyHTemp<=CoutM2 xor (not HourKey_i);
	
	S1_Map: Counter port map(
	CountClk=> clk_i,
	N=>N9,
	count=>CountS1,
	cout=>CoutS1);	
	
	S2_Map: Counter port map(
	CountClk=> CoutS1,
	N=>N5,
	count=>CountS2,
	cout=>CoutS2);

	M1_Map: Counter port map(
	CountClk=>KeyMTemp ,
	N=>N9,
	count=>CountM1,
	cout=>CoutM1);	
	
	M2_Map: Counter port map(
	CountClk=> CoutM1,
	N=>N5,
	count=>CountM2,
	cout=>CoutM2);
	
	
	H1_Map: Counter port map(
	CountClk=> KeyHTemp,
	N=>N23,
	count=>CountH,
	cout=>CoutH);	
	process(CountH)
	begin
	case CountH is 
				when "00000" =>CountH2<="00000";CountH1<="00000";
				when "00001" =>CountH2<="00000";CountH1<="00001";
				when "00010" =>CountH2<="00000";CountH1<="00010";
				when "00011" =>CountH2<="00000";CountH1<="00011";
				when "00100"=>CountH2<="00000";CountH1<="00100";
				when "00101" =>CountH2<="00000";CountH1<="00101";
				when "00110" =>CountH2<="00000";CountH1<="00110";
				when "00111" =>CountH2<="00000";CountH1<="00111";
				when "01000" =>CountH2<="00000";CountH1<="01000";
				when "01001" =>CountH2<="00000";CountH1<="01001";
				
				when  "01010"=>CountH2<="00001";CountH1<="00000";			
				when "01011" =>CountH2<="00001";CountH1<="00001";
				when "01100" =>CountH2<="00001";CountH1<="00010";
				when "01101" =>CountH2<="00001";CountH1<="00011";
				when "01110" =>CountH2<="00001";CountH1<="00100";
				when "01111" =>CountH2<="00001";CountH1<="00101";
				when "10000" =>CountH2<="00001";CountH1<="00110";
				when "10001" =>CountH2<="00001";CountH1<="00111";
				when "10010" =>CountH2<="00001";CountH1<="01000";
				when "10011" =>CountH2<="00001";CountH1<="01001";
				
				when "10100" =>CountH2<="00010";CountH1<="00000";
				
				when "10101" =>CountH2<="00010";CountH1<="00001";
				when "10110" =>CountH2<="00010";CountH1<="00010";
				when "10111" =>CountH2<="00010";CountH1<="00011";
				when OTHERS=>NULL;
	end case;
	
	
	

	
	

	
	--	process(HourKey_i)
	--	begin	
	--		if (HourKey_i'EVENT and HourKey_i='1') then
	--			if h<23 then
	--					h<=h+1;
	--			else 
	--					h<=0; 
	--			end if;
	--		end if;
	--	end process;
	--	
	--	process(MinKey_i)
	--	begin	
	--	if (MinKey_i'EVENT and MinKey_i='1') then
	--			if  m<59 then
	--				m<=m+1;
	--			else
	--				m<=0;	
	--			end if;
	--		end if;
	--	end process;	
	
	
	
	--					if s1<9 then
	--						s1<=s1+1;
	--					else
	--						s1<=0;
	--						if s2<5 then 
	--							s2<=s2+1;
	--						else
	--							s2<=0;
	--							if m1<9 then
	--								m1<=m1+1;
	--							else
	--								m1<=0;
	--								if m2<5 then
	--									m2<=m2+1;
	--								else
	--									m2<=0;
	--									if h2<2 then
	--										if h1<9 then
	--											h1<=h1+1;
	--										else 
	--											h1<=0;
	--											h2<=h2+1;---可以斷定這里加一
	--										end if;
	--									elsif h2>1 then
	--										if h1<3 then
	--											h1<=h1+1;
	--										else 
	--											h1<=0;
	--											h2<=0;
	--										end if;
	--									end if;		
	--								end if;
	--							end if;
	--						end if;			
	--					end if;
	--				end if ; 
	--				
	--				if (MinKey_i'EVENT and MinKey_i='1') then ------可能要根據按鍵高電平有效還是低電平有效修改  假設按下接到地
	--					if 	m1<=9 then
	--						m1<=m1+1;
	--					else
	--						m1<=0; 
	--						if m2<=5 then 
	--							m2<=m2+1;
	--						else 
	--							m2<=0;	
	--						end if;
	--					end if;
	--				end if;
	--				if (HourKey_i'EVENT and HourKey_i='1') then  ------可能要根據按鍵高電平有效還是低電平有效修改
	--					if h2<2 then
	--						if h1<9 then
	--							h1<=h1+1;
	--						else 
	--							h1<=0;
	--							h2<=h2+1;---可以斷定這里加一
	--						end if;
	--					elsif h2>1 then
	--						if h1<3 then
	--							h1<=h1+1;
	--						else 
	--							h1<=0;
	--							h2<=0;
	--						end if;
	--					end if;
	--				end if;	 
	--		
	--	
	
	--
	--		
	--		IF(clk_i'EVENT and clk_i='1')then 
	--		if (HourKey_i='0') then
	--				if h<23 then
	--						h<=h+1;
	--				else 
	--						h<=0; 
	--				end if;
	--			end if;
	--			
	--		if ( MinKey_i='0') then
	--			if  m<59 then
	--				m<=m+1;
	--			else
	--				m<=0;	
	--			end if;
	--		end if;
	--		
	--				if s<59 then
	--					s<=s+1;
	--				else
	--					s<=0;
	--					if m<59 then
	--						m<=m+1;
	--					else
	--						m<=0;
	--						if h<23 then
	--							h<=h+1;
	--						else 
	--							h<=0; 
	--						end if;
	--					end if;
	--				end if;
	--			
	--	
	--		
	--		end if;	
	--
	--			
	--		
	
	--		
	--
	--		
	--		h1<=h mod 10;
	--		h2<=(h - h1)/10;
	--		
	--		m1<=m mod 10;
	--		m2<=(m - m1)/10;
	--		
	--		s1<=s mod 10;
	--		s2<=(s - s1)/10;
	--		
	--	
	--		
	
	s1<=CONV_INTEGER(CountS1); 
	s2<=CONV_INTEGER(CountS2);
	m1<=CONV_INTEGER(CountM1);
	m2<=CONV_INTEGER(CountM2);
	h1<=CONV_INTEGER(CountH1);
	h2<=CONV_INTEGER(CountH2);
	CurrentTimeBCD(3 downto 0) <= std_logic_vector(to_unsigned(s1, 4));
	CurrentTimeBCD(7 downto 4) <= std_logic_vector(to_unsigned(s2, 4));
	
	CurrentTimeBCD(11 downto 8) <= std_logic_vector(to_unsigned(m1, 4));
	CurrentTimeBCD(15 downto 12) <= std_logic_vector(to_unsigned(m2, 4));
	
	CurrentTimeBCD(19 downto 16) <= std_logic_vector(to_unsigned(h1, 4));
	CurrentTimeBCD(23 downto 20) <= std_logic_vector(to_unsigned(h2, 4));		
	end process;
	
	
	
	CurrentTimeBCD_o<=CurrentTimeBCD;
end behavior;


仿真結果如下
小時

分鍾

秒鍾

下圖中輸出CurrentTimeBCD_o旁邊的數值105238表示帶有時間信息的BCD碼表示的時間10點52分38秒

頂層模塊

頂層模塊就是把上面各個模塊根據下圖用線連接起來。下圖為簡潔只畫了一個按鍵
稍微分析端口:
輸入:按鍵1、按鍵2、時鍾輸入
輸出:6位的位選信號、8位的段碼信號

代碼如下

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity DigitalClock is	 
	port(
		DigitalClockClk_i:IN STD_LOGIC;
		DigitalClockKeyM_i:IN STD_LOGIC;
		DigitalClockKeyH_i:IN STD_LOGIC;
		
		DigitalClockPosition_o:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
		DigitalClockSection_o: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
	
end DigitalClock;

architecture rtl of DigitalClock is	
	
	component ClkDiv is
		port(
			clk_i:IN STD_LOGIC;
			N_i:  IN STD_LOGIC_VECTOR(9 DOWNTO 0);
			clk_o:OUT STD_LOGIC);
	end component; 
	
	component JitterElimination is	
		port(
			key: IN STD_LOGIC;
			clk_i:IN STD_LOGIC;
			DLY_OUT:OUT STD_LOGIC);
		
	end component; 
	
	component LEDScan is 
		port(
			CurTime_i:  IN STD_LOGIC_VECTOR(23 DOWNTO 0); 
			clk_i:IN STD_LOGIC;
			Position_o:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
			Section_o: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
	end component; 	
	
	component Contrl is 
		port(
			MinKey_i:IN STD_LOGIC;
			HourKey_i:IN STD_LOGIC;
			clk_i:IN STD_LOGIC;
			CurrentTimeBCD_o: OUT STD_LOGIC_VECTOR(23 downto 0));
	end component;
	signal N1: STD_LOGIC_VECTOR(9 DOWNTO 0):="0000100010";
	signal Clk1M: STD_LOGIC:='0';
	
	signal N2: STD_LOGIC_VECTOR(9 DOWNTO 0):="1111101000"; 
	signal Clk1k: STD_LOGIC:='0';
	
	signal N3: STD_LOGIC_VECTOR(9 DOWNTO 0):="0000001010";
	signal Clk100Hz: STD_LOGIC:='0';  
	
	signal N4: STD_LOGIC_VECTOR(9 DOWNTO 0):="0000000010";
	signal Clk50Hz: STD_LOGIC:='0';
	
	signal N5: STD_LOGIC_VECTOR(9 DOWNTO 0):="0000110010";
	signal Clk1Hz: STD_LOGIC:='0'; 
	
	signal K1:STD_LOGIC:='1';--未按下 
	signal K2:STD_LOGIC:='1';--未按下
	
	signal BCD:STD_LOGIC_VECTOR(23 downto 0):="000000000000000000000000";
	
begin 
	
	Clock_Map: ClkDiv port map(
			clk_i=>DigitalClockClk_i,
			N_i=>N1,
			clk_o=>Clk1M);
			
	Clock_Map2: ClkDiv port map(
			clk_i=>Clk1M,
			N_i=>N2,
			clk_o=>Clk1k); 
			
	Clock_Map3: ClkDiv port map(
			clk_i=>Clk1k,
			N_i=>N3,
			clk_o=>Clk100Hz);
			
	Clock_Map4: ClkDiv port map(
			clk_i=>Clk100Hz,
			N_i=>N4,
			clk_o=>Clk50Hz); 
			
	Clock_Map5: ClkDiv port map(
			clk_i=>Clk50Hz,
			N_i=>N5,
			clk_o=>Clk1Hz); 
	
	KeyMin_Map:JitterElimination port map(
			key=>DigitalClockKeyM_i,
			clk_i=>Clk100Hz,
			DLY_OUT=>K1);
	KeyHour_Map:JitterElimination port map(
			key=>DigitalClockKeyH_i,
			clk_i=>Clk100Hz,
			DLY_OUT=>K2); 
	Contrl_Map: Contrl port map(
			MinKey_i=>K1,
			HourKey_i=>K2,
			clk_i=>Clk1Hz,
			CurrentTimeBCD_o=>BCD);
			
	LEDScan_Map: LEDScan port map(
			CurTime_i=>BCD, 
			clk_i=>Clk1k,
			Position_o=>DigitalClockPosition_o,
			Section_o=>DigitalClockSection_o);
	
end rtl;

由於33.8688Mhz太大,軟件仿真時間會比較慢,所以我沒有把軟件仿真圖放出來。等過些時候到FPGA板子上驗證

實驗結果:符合設計預期結果,時分秒顯示、按鍵都正常。

誤差分析

由於1Mhz的時鍾是由33.8688Mhz經過34分頻生成的,所以每秒會有0.1078s的誤差,也就是說1s過后此數字鍾覺得時間過了1.1078s。分頻方面我欠考慮了,如果想要提高精度要在分頻方面思考。

生成原理圖

尾聲

新司機上路,各位系好安全帶


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM