FC2カウンター FPGAの部屋 The Simple MicroBlaze Microcontroller 9 (SCCB回路の変更、設定SCCBレジスタ)
FC2ブログ

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

FPGAの部屋

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

The Simple MicroBlaze Microcontroller 9 (SCCB回路の変更、設定SCCBレジスタ)

さて、前回でロータリーエンコーダを使用することができた
今度は、SCCBレジスタの設定回路(SCCBインターフェース回路)をSMMから制御できるようにハードウェアを変更することと、LCDに表示して設定するSCCBレジスタを決定した。設定するSCCBレジスタの決定には、特殊電子回路株式会社の”OV7670で作るUSBカメラ”のページを参考にさせて頂いた。
最初に設定するレジスタの仕様を下に示す。
SMM_40_101209.png

AGC、AWB、AECのON, OFFと値、MIRRORのON, OFFを設定できるようにした。LCDの1桁目は設定する項目 (AGC, AWBなど)の値を表示する。ロータリーエンコーダのセンタースイッチを押すと編集モードに入って、1行目の後ろにEを表示する。編集モードでは、表示されている項目のON, OFFまたは値をロータリーエンコーダの右、または左回転で変更することができる。もう一度ロータリーエンコーダのセンタースイッチを押すと、編集モードから抜けて表示モードに戻る。この時に、ロータリーエンコーダの右、または左回転すると、表示する項目を移動できる。
LCDの2桁目は、全体を上図のように表示する。GはAGCがONであることを示し、BはAWBがONであること、EはAECがONであること、MはMIRRORがONであることを示す。OFFの時には表示は消える。

次に、SCCBインターフェース回路の変更点だ。
SCCBインターフェース回路の説明は、”SCCBインターフェース回路の説明1(SCCB_Reg_Controller.vhd)”、”SCCBインターフェース回路の説明2(freqdiv.vhd、SCCB_reg_values_ROM.vhd)”、”SCCBインターフェース回路の説明3(One_Transaction_SCCB.vhd)”を参照してください。
この中のSCCB_Reg_Controller.vhd にaddr_data、ad_enable、SCCB_busy の3つのポートを追加した。addr_dataは全体で16ビットで、上位8ビットがアドレス、下位8ビットがデータとなる。ad_enableはaddr_dataの値が有効でSCCBレジスタへの書き込みを示す1パルスの信号だ。SCCB_busyは、現在ステートマシンがSCCBレジスタに書き込み中を示す。これは、ステータス信号として、SMM (The Simple MicroBlaze Microcontroller) からReadすることができるようにする。

entity SCCB_Reg_Controller is
    port(
        clk : in std_logic; -- クロック
        reset  : in std_logic; -- リセット
        addr_data : in std_logic_vector(15 downto 0); -- SMMから設定されるSCCB設定レジスタのアドレスとデータ
        ad_enable : in std_logic; -- addr_data信号のイネーブルパルス
        SCCB_busy : out std_logic; -- SCCBレジスタを設定中を表すbusyフラグ
        SCL : out std_logic; -- SCCBのクロック
        SDA : out std_logic -- SCCBのデータ
    );
end SCCB_Reg_Controller;


初期化時に、SCCBインターフェース回路は、SCCB_reg_values.data の設定値を全て設定するが、その後はSMMの要求で、SCCBレジスタに設定値を書きこむように変更した。初期化設定時には、SCCB_busyを1にしておいて、SMMにSCCBインターフェース回路がbusyであることを知らせる。初期化後はaddr_data、ad_enableによるSMMからのレジスタ書き込みを行うことができるが、SMMはその前にSCCB_busyフラグを読んで、SCCBインターフェース回路がbusyでないことを確かめてから、レジスタの設定を行う。
下にSCCB_Reg_Controller.vhd の変更箇所を示す。

    -- One_Transaction_SCCB のインスタンス
    One_Transaction_SCCB_inst : One_Transaction_SCCB port map(
        clk => clk,
        reset => reset,
        SCCB_address => SCCB_address,
        SCCB_data => SCCB_data,
        op_enable => op_enable,
        start_pulse => SCCB_start_pulse,
        end_pulse => end_pulse,
        SCL => SCL,
        SDA => SDA
    );
    -- セレクタ、初期化が終了するまではROMのデータを選択して、終了した後ではSMMからの設定を選択する
    SCCB_address <= ROM_data(15 downto 8) when cs_reg_set/=end_state else addr_data(15 downto 8);
    SCCB_data <= ROM_data(7 downto 0) when cs_reg_set/=end_state else addr_data(7 downto 0);
    SCCB_start_pulse <= start_pulse when cs_reg_set/=end_state else ad_enable;
    
    -- SCCB_busyの制御
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_SCCB_busy <= idle_SCCB_busy;
                SCCB_busy_node <= '1';
            else
                case cs_SCCB_busy is
                    when idle_SCCB_busy =>
                        if cs_reg_set=end_state then -- 初期設定が終了
                            cs_SCCB_busy <= initialize_end;
                            SCCB_busy_node <= '0';
                        end if;
                    when initialize_end =>
                        if ad_enable='1' then -- SMMのSCCBレジスタ設定開始
                            cs_SCCB_busy <= SCCB_setting;
                            SCCB_busy_node <= '1';
                        end if;
                    when SCCB_setting =>
                        if end_pulse='1' then -- SMMのSCCBレジスタ設定終了
                            cs_SCCB_busy <= initialize_end;
                            SCCB_busy_node <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process;
    SCCB_busy <= SCCB_busy_node;


ここで、cs_reg_setはステートマシンのステートを示す信号で、end_stateに遷移していると初期化が終了したことを示している。

次に、SMMとのインターフェース回路lcd_rot_cont.vhdだが、ここにSCCB_addr_data、SCCB_ad_enable、SCCB_busyポートを追加した。

entity lcd_rot_cont is
    Port (     clk : in  STD_LOGIC;
                Reset : in  STD_LOGIC;
                rot_a : in std_logic;
                rot_b : in std_logic;
                rot_center : in std_logic;
                Button_S : in STD_LOGIC;
                LCD_DB : out STD_LOGIC_VECTOR (7 downto 0);
                LCD_RS : out STD_LOGIC;
                LCD_RW : out STD_LOGIC;
                LCD_E : out STD_LOGIC;
                SCCB_addr_data : out std_logic_vector(15 downto 0); -- SMMから設定されるSCCB設定レジスタのアドレスとデータ
                SCCB_ad_enable : out std_logic; -- addr_data信号のイネーブルパルス
                SCCB_busy : in std_logic -- SCCBレジスタを設定中を表すbusyフラグ
    );
end lcd_rot_cont;


0040番地にSCCBインターフェース回路へのアドレス、データを書き込む回路を追加した。

CS_SCCB_wr <= '1' when ((ADDR = X"0040") and CS = '1' and RNW = '0') else '0' ;


SCCB_ad_enableを生成する回路を追加して、アドレス、データの16ビットは下位16ビットに割り当てた。

    -- SCCB_ad_enable の生成
    process(clk) begin
        if clk'event and clk='1' then
            if Reset='1' then
                SCCB_ad_enable <= '0';
            else
                if CS_SCCB_wr='1' and CS_SCCB_wr_1d='0' then
                    SCCB_ad_enable <= '1';
                else
                    SCCB_ad_enable <= '0';
                end if;
            end if;
        end if;
    end process;
    
    SCCB_addr_data <= DOUT(0 to 15);  -- 上位16ビット


(修正)
SCCB_addr_data <= DOUT(0 to 15); -- 上位16ビット に修正しました。元は下位16ビットでした。アドレスが面倒になるので上位16ビットに変更です。
  1. 2010年12月09日 05:12 |
  2. SMM
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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