2ch・シリアル8bitADコンバータ(MAX1118) DIP化モジュールキット: 組立キット 秋月電子通商-電子部品・ネット通販
pp.414-416
CH0をAD変換してみる。クロックはテキストどおりアイドル時Hiにしたが、データシートによればアイドル時Loでもよい。!スレーブセレクトして7.5 usほど待つと変換が済むので、パルスを順次送り込んでビット7から順番に8ビットを読み出し、!スレーブセレクトを解除する。
rd信号の立ち上がりをきっかけに処理を始める。
library ieee; use ieee.std_logic_1164.all; entity SPI_interface_for_MAX1118 is port( clk, rst: in std_logic; rd : in std_logic; MISO : in std_logic; SSn, SCLK : out std_logic; received_data: out std_logic_vector(7 downto 0) ); end entity; architecture rtl of SPI_interface_for_MAX1118 is signal clk_5MHZ: std_logic; signal t, tmax : natural range 0 to 37; type state_type is (idle, convert, read_data, hold); signal pr_state, nx_state: state_type; begin -- ソースクロック(48 MHz)を10分周してSPIクロック(約5 MHz)を生成する。 process(clk) variable count: natural range 0 to 4; begin -- 5クロックサイクルごとにトグルする。 if rising_edge(clk) then if count = 4 then clk_5MHZ <= not clk_5MHZ; count := 0; else count := count + 1; end if; end if; end process; -- ステートを保持するためのレジスタ process(clk_5MHZ, rst) begin if rst then pr_state <= idle; elsif rising_edge(clk_5MHZ) then pr_state <= nx_state; end if; end process; -- ステートを遷移させるための論理回路 process(all) begin case pr_state is when idle => if rd then nx_state <= convert; else nx_state <= idle; end if; when convert => if t = tmax then nx_state <= read_data; else nx_state <= convert; end if; when read_data => if t = tmax then nx_state <= hold; else nx_state <= read_data; end if; when hold => if not rd then nx_state <= idle; else nx_state <= hold; end if; end case; end process; -- ステートマシン出力を決めるための論理回路 -- テキストと違うがロジアナでうまくデコードできないためSSnをレジスタに通して半拍遅らせた。 process(all) variable SSn_tmp: std_logic; begin case pr_state is when idle => SSn_tmp:= '1'; SCLK <= '1'; when convert => SSn_tmp:= '0'; SCLK <= '1'; -- スレーブセレクト when read_data => SSn_tmp:= '0'; SCLK <= clk_5MHZ; when hold => SSn_tmp:= '1'; SCLK <= '1'; -- スレーブセレクトを解除 end case; if falling_edge(clk_5MHz) then SSn <= SSn_tmp; end if; end process; -- SPIクロックに同期してビット7からビット0まで順番に読み出す。 process(clk_5MHZ) begin if rising_edge(clk_5MHZ) then if pr_state = read_data then received_data(7 - t) <= MISO; end if; end if; end process; -- タイマー process(all) begin case pr_state is when convert => tmax <= 37; -- 変換中タイマーのトップ値(約200 ns * 38 = 7.5 us) when read_data => tmax <= 7; -- 読み出し中タイマーのトップ値 when others => tmax <= 0; end case; if rising_edge(clk_5MHZ) then if pr_state /= nx_state then t <= 0; elsif t /= tmax then t <= t + 1; end if; end if; end process; end architecture;