FC2カウンター FPGAの部屋 SCCBインターフェース回路の説明2(freqdiv.vhd、SCCB_reg_values_ROM.vhd)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

SCCBインターフェース回路の説明2(freqdiv.vhd、SCCB_reg_values_ROM.vhd)

次にまずはfreqdiv.vhd から。freqdiv.vhd は25MHzから200KHzに分周する回路だ。ただ単に分周するのではなく、200KHzに相当する間隔、つまり5usec ごとに25MHzクロック1クロック分の幅 (40nsec) 分のイネーブル信号を出力する。それがop_ena だ。なんでこんなことをするのかと言うと、分周してクロック周波数を200KHz とすると、25MHz で動作する回路とのインターフェースが面倒だからだ。ツール、つまりISEでも自動では面倒を見てくれない。お互いの信号のやりとりは非同期としての扱いになってしまう。25MHzクロック1クロック分の幅 (40nsec) 分のイネーブル信号だったら、回路動作は25MHzクロックでの動作となるので、ツールが自動的(制約を掛けておけば)に良いようにしてくれる。ということで、このような構成になっている。下にVHDLコードを示す。

-- Frequncy Divider 
-- 200KHz clock
-- マスタークロックを200KHzのop_enaに分周します。

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

entity FreqDiv is
    generic(
        divisor : integer := 125
    );
    port(
        clk, reset : in std_logic;
        op_ena : out std_logic
    );
end FreqDiv;

architecture RTL of FreqDiv is
signal lcnt : std_logic_vector(15 downto 0);
begin
    process(clk) begin -- Enable frequency is 200KHz
        if clk'event and clk='1' then
            if reset='1' then
                lcnt <= (others => '0');
            elsif lcnt = conv_std_logic_vector(divisor, 16)-1 then
                lcnt <= (others => '0');
            else
                lcnt <= lcnt + 1;
            end if;
        end if;
    end process;
    
    process(clk) begin
        if clk'event and clk='1' then
            if lcnt = conv_std_logic_vector(divisor, 16)-1 then
                op_ena <= '1';
            else
                op_ena <= '0';
            end if;
        end if;
    end process;
end RTL;


次は、SCCB_reg_values_ROM.vhd だが、これは、”VHDLでのブロックRAMや分散RAMの初期化(16進数で書かれた外部データファイル)”で説明した大体そのままなのだが、RAMではなくROMになっている。下にVHDLコードを示す。

-- SCCB_reg_values_ROM.vhd
-- SCCBプロトコル・コントローラを実装してSCCBレジスタに書き込む値をセーブしてある ROM。書き込みデータは SCCB_reg_values.data にセーブしておく。
-- SCCB_reg_values.data のフォーマット"1280" 最初の2キャラクタが16進形式のアドレス、次の2キャラクタが16進形式のデータ。例は12番地に80を書く
-- SCCB_reg_values_ROM.data には必ず256行のデータを用意しておく。アドレスがFFの場合はレジスタ・アクセスはそこで終了する。

library IEEE, STD;
use IEEE.std_logic_1164.all;
use STD.textio.all;
use IEEE.std_logic_textio.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
-- pragma translate_on

entity SCCB_reg_values_ROM is
    port(
        clk : in std_logic; -- Clock
        address : in std_logic_vector(7 downto 0);
        dout : out std_logic_vector(15 downto 0)
    );
end SCCB_reg_values_ROM;

architecture RTL of SCCB_reg_values_ROM is
type RamType is array(0 to 255) of std_logic_vector(15 downto 0);
impure function InitRamFromFile (RamFileName : in string) return RamType is
    FILE RamFile : text is in RamFileName;
    variable RamFileLine : line;
    variable RAM : RamType;
begin
    for I in RamType'range loop
        readline (RamFile, RamFileLine);
        hread (RamFileLine, RAM(I));
    end loop;
    return RAM;
end function;
signal RAM : RamType := InitRamFromFile("SCCB_reg_values.data");
begin
    process(clk) begin
        if clk'event and clk='1' then
            dout <= RAM(conv_integer(address));
        end if;
    end process;
end RTL;


SCCB_reg_values.dataの一部を下に示す。

ACDF
FF00
0000

  1. 2009年12月23日 19:50 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog.fc2.com/tb.php/1330-858e1bf4
この記事にトラックバックする(FC2ブログユーザー)