· 

SPIハードをFPGAで(2)

SPIハードをVHDLで記述して、GHDLでは動いていたので、QuartusPrimeでシミュレーションしてみます。

そういえば通常SPIにはいくつかのオプションがありますが、今回はスピードだけいじれるものです。悪しからず。

 

Quartus Prime Lite EditionはVersion18.1を使います。Ver19以降はWSLを必要とするんだけど、設定がよくわからん。Ver18以前はcygwinを自前でインストールしてくれるのでラク。まぁいつか解決しよう、、、いつか、、、

 

ではQuartusを起動する。

New Project Wizardを押す。

反射的に「Next>」を押す。そう、反射的に。

フォルダ名とプロジェクト名を入れる。プロジェクト名を毎回おんなじにしておくと、複製が容易になると思う。なぜstudy5なのか、、、これ書くまでにいろいろ検討しているんですよ。涙ぐましい地道な作業の上にすべては成り立っているのです。報われないことが多すぎてホントしんどい。

そして「Next>」を押す。

こういうのが出たら、反射的に「Yes」を押す。そう、反射的に。

Emptyからやるので、そのまま「Next>」。

ここで、ファイルを入れ込めるみたいだけど、後でやるので何もせずに「Next>」。

このボードを使うので、こうする。このボードちょっと前まで購入できてたのに、今日見たら買えなくなってた。今後買うのならこれしかない。FPGA評価キットって高価だよなー。そして相変わらずの半導体不足、、、MAX10単品でも入手できない、、、やっぱりマイナーなLatticeのほうがホビーユーザーには手が届きやすいかな、、、まぁ今回はIntel MAX10で。

無料で使えるModelSim-Alteraを選択。VHDL派であることを主張。最近、Verilog-HDLのほうが魅力が高まっている気がする。OpenCoresでもVerilogの投稿のほうが多いような、、、

そして、反射的に「Finish」。

トップレベルのソースを作るので、File-->New。

ここでもVHDL派であることを主張。

とりあえず、まっさらな状態で名前を付けて保存。

「FPGA.vhd」として保存しようとするので、そのまま「保存」。

FPGAフォルダにMySPIフォルダを作ってGHDLでシミュレーションしたVHDLファイルを入れる。

QuartusでAssignments-->Settings...を選択する。

追加するファイルを選ぶダイアログを表示させる。

選んで開く。

こうなるので、OK。

システムクロックとSPIの基準クロックはテストベンチで与えるではなく、PLLで生成します。

たいへん安易なファイル名にします。

今回のボードは48MHzのクリスタルオシレータがついているので48MHzとします。

今回はオプションの入出力は使いません。

よくわからんので、そのままNext。

クロック源を切り替えられるらしいけど、無効のままNext。

ややこしいものは使わない。

C0をシステムクロックにします。欲をかいて100MHzにします。

SPIの基準は2MHzにします。2MHzでHとLをだすと1Mbit/secになります。

c2は使わない。

c3は使わない。

c4は使わない。

必要かどうかはわからんけど、有効にしておく。

おそらく、要らんと思うものまで有効にしてFinish。

Yesを押すと、プロジェクトにPLLを追加してくれる。

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY altera;
USE altera.altera_syn_attributes.ALL;

ENTITY FPGA IS
        PORT (
                NSEND : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
                NCLKDIV : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
                BUSY : OUT STD_LOGIC;
                INIT : IN STD_LOGIC;
                WDATA : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
                RDATA : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
                EN : IN STD_LOGIC;
                SCK : OUT STD_LOGIC;
                MOSI : OUT STD_LOGIC;
                MISO : IN STD_LOGIC;
                clk48 : IN STD_LOGIC

        );
END FPGA;

ARCHITECTURE ppl_type OF FPGA IS
        SIGNAL res_n : STD_LOGIC;
        SIGNAL por_n : INTEGER RANGE 0 TO 1;
        SIGNAL por_count : INTEGER RANGE 0 TO 65535;
        CONSTANT POR_MAX : INTEGER := 127;

        COMPONENT MySPI IS
                PORT (
                        NSEND : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
                        NCLKDIV : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
                        CLKIN : IN STD_LOGIC;
                        CLKOUT : OUT STD_LOGIC;
                        CLKSYS : IN STD_LOGIC;
                        BUSY : OUT STD_LOGIC;
                        INIT : IN STD_LOGIC;
                        WDATA : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
                        RDATA : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
                        OUTP : OUT STD_LOGIC;
                        INP : IN STD_LOGIC;
                        EN : IN STD_LOGIC
                );
        END COMPONENT MySPI;
        signal EN_internal : std_logic;

        COMPONENT PLL IS
                PORT (
                        inclk0 : IN STD_LOGIC := '0';
                        c0 : OUT STD_LOGIC;
                        c1 : OUT STD_LOGIC
                );
        END COMPONENT PLL;
        SIGNAL clk100 : STD_LOGIC;
        SIGNAL clk2 : STD_LOGIC;

BEGIN
        MySPI_inst : COMPONENT MySPI PORT MAP(
                NSEND => NSEND,
                NCLKDIV => NCLKDIV,
                CLKIN => clk2,
                CLKOUT => SCK,
                CLKSYS => clk100,
                BUSY => BUSY,
                INIT => INIT,
                WDATA => WDATA,
                RDATA => RDATA,
                OUTP => MOSI,
                INP => MISO,
                EN => EN_internal
        );
        PLL_inst : PLL PORT MAP(
                inclk0 => clk48,
                c0 => clk100,
                c1 => clk2
        );
        --internal reset
        PROCESS (clk48) BEGIN
                IF clk48'event AND clk48 = '1' THEN
                        IF por_count = POR_MAX THEN
                                por_n <= 1;
                                por_count <= por_count;
                        ELSE
                                por_n <= 0;
                                por_count <= por_count + 1;
                        END IF;
                END IF;
        END PROCESS;
        res_n <= '1' WHEN por_n = 1 ELSE '0';
        EN_internal <= EN when res_n='1' else '0';
END;

FPGA.vhdはこうする。QuartusというかModelSimではテストベンチは別途作るので、MySPIのインスタンスとPLLのインスタンスとPLL起動待ちを実装する。

Analysis  & Synthesisを右クリックしてStartを押すとなんかやってくれる。

こんな感じでできたらしい。

 

、、、道のりが長いのでいったんここで切る。