FPGAでグラフィックス液晶モジュール用の信号を生成する(その2)

_DSC9180.JPG
前回の「FPGAでグラフィックス液晶モジュール用の信号を生成する(その1)」では鈴商で販売されているグラフィック液晶(384x192ドット、モノクロ)を利用するための信号の内、CPとLOAD信号生成部分をVHDLで作成し、ModelSimで信号のシュミレーションまでをした。
今回はさらにほかのIO1、DF信号の生成部も作成し、実際にFPGA(Spartan3E)へ書き込み動作を確認する。Spartan3EはDesign Wave Magazine 2007年7月号に付属していた基板を利用した。


fpga_glcd_02_01.gif
前回のプロジェクトをISE WebPackで開き、さらに信号を作るためソースコードを追加する。「Project」メニューの「New Source」を選択する。


fpga_glcd_02_02.gif
ソースコードの形式は「VHDL Module」、ファイル名は「GenerateLineClk」とした。残る信号はIO1、DF、Dの3信号だが、これらのうちIO1とDF信号は行単位(Y軸方向)の信号になる。CP信号からこれらを生成してもいいのだが、カウントするクロックするが大きくなるので1行ごとに1クロック出力するラインクロックを作って、それに基づいてIO1とDF信号を作ることにした。

fpga_glcd_02_03.gif
「CP」と「LINECLK」を追加してそれぞれ「in」と「out」に設定する。

fpga_glcd_02_04.gif
ラインクロックは1行につき1クロック生成したいので、1行(CP信号100クロック)でHighとLowが起きるように7ビットカウンターを作成した。


----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 13:59:58 07/03/2007
-- Design Name:
-- Module Name: GenerateLineClk - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity GenerateLineClk is
Port ( CP : in STD_LOGIC;
LINECLK : out STD_LOGIC);
end GenerateLineClk;

architecture Behavioral of GenerateLineClk is

signal TMP : STD_LOGIC_VECTOR( 6 downto 0 ) := "0000000";
begin

process (CP)
begin
if CP'event and CP='1' then
TMP <= TMP + "0000001";
if TMP < "0110010" then -- 50
LINECLK <= '1';
else
LINECLK <= '0';
if TMP = "1100011" then -- 99
TMP <= "0000000";
end if;
end if;
end if;
end process;

end Behavioral;






fpga_glcd_02_05.gif
次にIO1信号を生成するためのソースコードを追加する。「Project」メニューの「New Source」を選択して「VHDL Module」でファイル名が「GenerateIO1」とする。
そして「LINECLK」と「IO1」を入力してそれぞれ「in」と「out」に設定する。

fpga_glcd_02_06.gif
ソースコードが生成したらIO1信号生成用のVHDLを記述する。IO1信号は画面内で1行目に該当するときのみHighとなる信号のため、8ビットカウンターで0のときHigh、191以下のときにLowになるようにする。


----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:02:18 07/03/2007
-- Design Name:
-- Module Name: GenerateIO1 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity GenerateIO1 is
Port ( LINECLK : in STD_LOGIC;
IO1 : out STD_LOGIC);
end GenerateIO1;

architecture Behavioral of GenerateIO1 is

signal TMP : STD_LOGIC_VECTOR( 7 downto 0 ) := "00000000";
begin

process (LINECLK)
begin
if LINECLK'event and LINECLK='1' then
TMP <= TMP + "00000001";

if TMP < "00000001" then
IO1 <= '1';
else
IO1 <= '0';
if TMP = "10111111" then -- 191
TMP <= "00000000";
end if;
end if;
end if;
end process;

end Behavioral;





fpga_glcd_02_07.gif
さらにDF信号を生成するためのソースコードを追加する。「Project」メニューの「New Source」を選択して「VHDL Module」でファイル名が「GenerateDF」とする。
そして「LINECLK」と「DF」を入力してそれぞれ「in」と「out」に設定する。

fpga_glcd_02_08.gif
ソースコードが生成したらDF信号生成用のVHDLを記述する。DF信号は連続した2画面を見たときに最初の画面のときにHigh、次の画面のときにLowとなる信号のため、ラインクロックが192未満のときにHigh、383(=192×2)以下のときにLowになるようにする。


----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:04:05 07/03/2007
-- Design Name:
-- Module Name: GenerateDF - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity GenerateDF is
Port ( LINECLK : in STD_LOGIC;
DF : out STD_LOGIC);
end GenerateDF;

architecture Behavioral of GenerateDF is

signal TMP : STD_LOGIC_VECTOR( 8 downto 0 ) := "000000000";
begin

process (LINECLK)
begin
if LINECLK'event and LINECLK='1' then
TMP <= TMP + "000000001";

if TMP < "11000000" then -- 192
DF <= '1';
else
DF <= '0';
if TMP = "101111111" then -- 383(=192x2-1)
TMP <= "000000000";
end if;
end if;
end if;
end process;

end Behavioral;





fpga_glcd_02_09.gif
これでCP、LOAD、IO1、DFの各信号生成用のVHDLができた。最後にGenerateSignals.vhdを編集して、これらのモジュールを関連付ける。


----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 13:45:42 07/03/2007
-- Design Name:
-- Module Name: GenerateSignals - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity GenerateSignals is
Port ( CLOCK : in STD_LOGIC;
LOAD : out STD_LOGIC;
CP : out STD_LOGIC;
D : out STD_LOGIC_VECTOR(3 downto 0);
IO1 : out STD_LOGIC;
DF : out STD_LOGIC);
end GenerateSignals;

architecture Behavioral of GenerateSignals is

signal CP_TMP : STD_LOGIC;
signal LOAD_TMP : STD_LOGIC;
signal DF_TMP : STD_LOGIC;
signal IO1_TMP : STD_LOGIC;
signal LINECLOCK : STD_LOGIC;

component GenerateCP
Port ( CLK : in STD_LOGIC;
CP : out STD_LOGIC);
end component;

component GenerateLOAD
Port ( CP : in STD_LOGIC;
LOAD : out STD_LOGIC);
end component;

component GenerateIO1
Port ( LINECLK: in STD_LOGIC;
IO1 : out STD_LOGIC);
end component;

component GenerateDF
Port ( LINECLK : in STD_LOGIC;
DF : out STD_LOGIC);
end component;

component GenerateLineClk
Port ( CP : in STD_LOGIC;
LINECLK : out STD_LOGIC);
end component;

begin

LOAD <= LOAD_TMP;
CP <= CP_TMP;
D(0) <= '1';
D(1) <= '1';
D(2) <= '0';
D(3) <= '0';
IO1 <= IO1_TMP;
DF <= DF_TMP;

u0: GenerateCP port map(
CLK => CLOCK,
CP => CP_TMP);

u1: GenerateLOAD port map(
CP => CP_TMP,
LOAD => LOAD_TMP);

u2: GenerateIO1 port map(
LINECLK => LINECLOCK,
IO1 => IO1_TMP);

u3: GenerateDF port map(
LINECLK => LINECLOCK,
DF => DF_TMP);

u4: GenerateLineClk port map(
CP => CP_TMP,
LINECLK => LINECLOCK);

end Behavioral;





fpga_glcd_02_10.gif
ここまでできたら一度保存してシュミレーションしてみる。「File」メニューの「Save All」を選択する。

fpga_glcd_02_11.gif
そして「ModelSim」を起動する。

fpga_glcd_02_12.gif
ModelSimが起動したら「Compile」メニューの「Compile」を選択する。

fpga_glcd_02_13.gif
そしてISE WebPackで作成したプロジェクトのフォルダを開き、「GenerateCP.vhd」、「GenerateDF.vhd」、「GenerateIO1.vhd」、「GenerateLineClk.vhd」、「GenerateLOAD.vhd」、「GenerateSignals.vhd」を選択して「Compile」ボタンを押す。

fpga_glcd_02_14.gif
コンパイルが終わったら「Done」ボタンを押して選択画面を閉じる。

fpga_glcd_02_15.gif
するとコンパイルしたファイルがツリー内の「work」ライブラリーに追加される。ここから「GenerateSignals」を右クリックして現れたメニューから「Simulate」を選択し、シュミレーション画面に切り替える。

fpga_glcd_02_16.gif
シュミレーション画面が開いたら「View」メニューの「Wave」で波形表示用ウインドウを開く。

fpga_glcd_02_17.gif
そしてシュミレーションしたい信号をドラッグ・アンド・ドロップする。今回はLOAD、CP、IO1、DFの各信号をシュミレートする。

fpga_glcd_02_18.gif
ドラッグ・アンド・ドロップしたらクロックの設定をする。「clock」を右クリックして現れたメニューから「Clock」を選択する。

fpga_glcd_02_19.gif
そして「Period」欄に「2」と入力する。今回も前回と同様にパルスのタイミングだけ見れればいいためクロックを2ピコ秒とした。

fpga_glcd_02_20.gif
クロックの設定まで終わったら、下の「Transcript」欄に「run 100000」と入力して10万ピコ秒のシュミレーションを行う。

fpga_glcd_02_21.gif
すると画面にシュミレーション結果が表示される。

fpga_glcd_02_22.gif
画面を見やすいように広げた。さらに全体が分かるように右クリックして現れたメニューから「Zoom Full」を選択する。

fpga_glcd_02_23.gif
すると現在のシュミレーション全体10万ピコ秒分が画面に表示される。IO1が1行目のみHigh、LOADが1行ごとにHighなどの信号状態を見れる。さらに必要に応じて「run 1000000」のようにシュミレーションし、拡大縮小表示して信号の生成タイミングが意図した通りか確認する。

fpga_glcd_02_24.gif
信号のシュミレーションが確認できたら、シュミレーターを終了して「ISE WebPack」の画面に戻る。そして次にユーザー制約ファイルによるピン配置の設定をする。
「Use Constraints」にある「Assign Package Pins」を右クリックして現れるメニューから「Run」を選択する。

fpga_glcd_02_25.gif
するとピン配置を設定するための「Xilinx PACE」が起動する。ここで左側の「Design Object List」ウインドウ内の「Loc」欄で使用するピンを指定する。
「CLOCK」を「P88」に、
「CP」を「P49」に、
「D<0>」を「P47」に、
「D<1>」を「P40」に、
「D<2>」を「P35」に、
「D<3>」を「P33」に、
「DF」を「P26」に、
「IO1」を「P23」に、
「LOAD」を「P18」に設定する。これらの内「CLOCK」以外の液晶パネル用信号線はDisign Wave Magazine 2007年7月号付録基板のCN2上のA17~A08に相当する。ほかのポートを使いたい場合は適宜変更する。設定が終わったら「Xilinx PACE」を閉じる。

fpga_glcd_02_26.gif
そして「Generate Programming File」を右クリックして現れるメニューから「Run」を選択してビルド(論理合成など)を行う。

fpga_glcd_02_27.gif
待つこと数分。無事に論理合成などが終わりビットストリームファイルが生成した。


_DSC9184.JPG
これでbitファイルからXSVFファイルを生成してFPGAに書き込み動かしてみた。

_DSC9185.JPG
かなり無駄な部分の多いVHDLソースコードになってしまったが画面にきちんと縦線を表示できた。
縦線なのはソースコード(GenerateSignals.vhd)内で固定値「0011」を指定しているためだ。CP信号が1MHzでは遅すぎるからか若干ちらつきが見られるがバックライトを点灯しなくてもくっきりと表示された。


カテゴリー「電子工作」 のエントリー