2009年05月31日

プリスケーラ

例のMMK(MAX II Micro Kit)で10[MHz]のクロック源が必要な状況になった。MAX II はPLLを内蔵していないので、内部にプリスケーラを用意する必要が出てくる。ここでは50[MHz]の発振器から10[MHz]を作ることを目的としているのだが、その信号をデューティ比0.5にしたいなら単純でなく、ちょっとwebで調べた限りそういうプリスケーラのコードが見つからなかったので自作することにした。

単純でない、というのは、例えばある周波数fの発振器を源にしてf/2n(除数が偶数)のクロックならばカウンタを用いて簡単に作れるが、f/(2n-1)(除数が奇数)の場合は、pos/neg両方のエッジを見ないとデューディ比が0.5にならないので一工夫要る、という意味だ(勿論、基準となる発振器のパルスのデューティ比が元々0.5であることを前提とした話)。

先ずVHDLコードを示す。
-----------------------------------------------------------
--
-- Frequency divider (prescaler)
--
-- Caution : DIV >= 2
-- LEN = roundup( log2( DIV ) )
--
-- Written by Masa. "Pressure~" Takahashi
--
-----------------------------------------------------------

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freqDiv is
GENERIC (
DIV : integer := 5; -- divider
LEN : integer := 3 -- counter length
);
PORT (
clk : in std_logic; -- clock
rstn : in std_logic; -- ~reset
--
dclk : out std_logic -- divided clock
);
end freqDiv;

ARCHITECTURE rtl of freqDiv is
signal count : std_logic_vector( LEN-1 downto 0 ); -- divide counter
signal pEdge : std_logic;
signal nEdge : std_logic;
begin
process( clk , rstn , count ) begin
if rstn = '0' then
count <= Conv_std_logic_vector( 0 , LEN );
pEdge <= '0';
nEdge <= '0';
elsif clk'event and clk = '1' then -- positive edge
if count = DIV-1 then
count <= Conv_std_logic_vector( 0 , LEN );
else
count <= count + 1;
end if;
if count >= DIV / 2 + ( DIV mod 2 ) then
pEdge <= '1';
else
pEdge <= '0';
end if;
elsif clk'event and clk = '0' then -- negative edge
if count > DIV / 2 then
nEdge <= '1';
else
nEdge <= '0';
end if;
end if;
end process;

dclk <= pEdge or nEdge when DIV mod 2 = 1 else pEdge;
end rtl;
DIVは2以上の除数(分周数)、LENはカウンタ長でlog2DIVを切り上げた整数を設定する。この場合 DIV=5 なので、f/5のプリスケーラという意味になる。コードが小さいので特に細かい解説は不要だと思う。結局、双方のエッジを元に1つのカウンタをインクリメントしたりすることは出来ないので、DIVが奇数の場合は各々個別にエッジを検出してデューティ比0.5になるように波形を作っているだけのことである。

なおDIVを偶数にした場合、コードの一部に意味を成さないロジックがあることになるが、それらは合成時に最適化され削除されるので心配は無用だ。最後に、clkに50[MHz]を入力した時のシミュレーション結果を↓に示しておく。(入力がデューティ比0.5のクロックなら)仕様通りの矩形波信号が出力されていることが判る。因みにこの回路は6LEsの資源で実現出来る。

freqDivSim.PNG

これとは別に、デューティ比は0.5にはならないがクロック周波数を有理数倍(但し0以上1未満)にするプリスケーラも別途作った。何れFPGA実験室の方に記事を書こうと思う。
posted by Masa at 14:59| Comment(0) | 実験 | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。