2014-12-05 67 views
0

我正在做這個項目,將輸出所需的頻率。對於大多數頻率我可以做出有效的代碼,但是當涉及頻率像300赫茲我有麻煩。VHDL脈衝發生器與任何頻率

因此,這裏是我的代碼大部分:

library ieee; 
use ieee.std_logic_1164.all;  

entity test is 
port(
    clk:in std_logic:='0'; 
    clk_o:buffer std_logic:='0' 
); 
end test; 

architecture Behavioral of test is 
begin 
process(clk) 
variable temp:integer range 0 to 1000000:=0; 
begin 
if(clk'event)then 
    temp:=temp+1; 
    if(temp>=1000000)then 
     clk_o<=not clk_o; 
     temp:=0; 
    end if; 
end if; 
end process; 
end Behavioral; 

,這將產生50赫茲的頻率,因爲我的FPGA的時鐘速度爲50MHz。所以首先我試圖把它分開,但問題是你不能產生300Hz,因爲50 * 10^6/300是166666.667等等。

然後,我看到你可以使時間類型的變量,使時間最後1/300,但後來我意識到它不合成合格,所以它是不好的。還有REAL類型的變量可以使它更準確,然後整數變量,但它也不合成合格。

所以我沒有想法,如果任何人都可以給我一些提示,我會非常感激。

+0

一個經典的選擇是分別累積小數部分,並在溢出或攜帶時將週期增加一個週期。 – 2014-12-05 14:05:37

+0

將你的時鐘頻率改爲300Hz的整數倍 – OllieB 2014-12-05 15:52:18

+0

如果計數器只應該在時鐘的上升沿增加if條件應該改爲if(clk'event和clk ='1')然後......。仿真會告訴您產生的預期頻率是原來的兩倍,因爲原始進程會在時鐘的上升沿和下降沿都觸發。 – damage 2014-12-05 22:30:42

回答

0

如果你只是使用166666,你只會過快0.0004%或4ppm。這是一個很小的錯誤,在實際的實現中它通常並不重要 - 你的50MHz振盪器可能比這個錯誤更多。 [編輯:正如在評論中指出的那樣,晶體振盪器很可能有10-20ppm的誤差,但也有其他類型的振盪器具有更高或更低的誤差(儘管50MHz FPGA時鐘可能是晶體)]

如果您真的需要擺脫0.0004%的錯誤,您可以使用DCM/MMCM/PLL(取決於您的FPGA的功能)將50MHz時鐘倍頻至150MHz,然後均勻地分頻至300 Hz。

正如Brian Drummond所提到的,您也可以使用0-2計數器計數到每3個週期中有166667個計數,另一個計數到166666,這樣可以避免累積相位誤差,如果您試圖保持同相擁有完美理想的300MHz信號源。

事實上,沒有真正的振盪器與廣告頻率完美匹配的原因是爲什麼RS232頻繁地重新同步到時鐘(以避免累積相位誤差),爲什麼更高速度傳輸使用源同步時鐘或時鐘和數據 - 恢復PLL。

+1

具有400 ppm誤差的振盪器是很多應用。對於便宜的振盪器來說,10 ppm更爲現實。 – OllieB 2014-12-05 15:54:33

+0

不夠公平,儘管我頻繁地運行串行鏈接3-4%,因爲每一端都有不同的時鐘可用,我不需要使用更好的時鐘資源(如果它們甚至可用)。工作中的高速數據鏈接也可以輕鬆處理1%的關閉。 – QuantumRipple 2014-12-05 16:02:01

+1

只有4ppm(不是400ppm; 0.0004%**是**百分比)是0.0004%? **會低於10ppm的晶體。 – QuantumRipple 2014-12-05 19:37:20