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

fpga_glcd_03_01.gif
前回の「FPGAでグラフィックス液晶モジュール用の信号を生成する(その2)」で鈴商で販売されている384×192ドットのモノクロ液晶モジュールにDesign Wave Magazine 2007年7月号付録のSpartan3Eで縦線を表示できるようになった。
今回はさらにFPGAのブロックRAMに画像データを格納して、任意の画像を表示できるようにする。

fpga_glcd_03_02.gif
Xilinx ISE WebPackで前回までに作成したプロジェクトを開く。そして画像データをプロジェクトに追加するため「Project」メニューの「New Source」を選択する。

fpga_glcd_03_03.gif
これまではソースコードの追加時は「VHDL Module」を選択したていたが、今回は「IP (Coregen & Archtecture Wizard)」を利用する。ファイル名は「ImageROM」とした。

fpga_glcd_03_04.gif
するとツリー形式でIPの選択画面が開く。ここで「Memories & Storage Elements」の「RAMs & ROMs」にある「Single Port Block Memory v6.2」を選択する。本当はDual Portのものを利用した方が後々使いやすいのだろうが、ブロックRAMを使うのは初めてなので単純なSingle Portのものにした。

fpga_glcd_03_05.gif
確認画面が出たら「Finish」でウイザードを終える。

fpga_glcd_03_06.gif
ウイザードが閉じると画面下部に「Customizing IP...」という表示がされ、バックで作業が行われる。

fpga_glcd_03_07.gif
そして20秒程度待つとブロックメモリーの設定画面が開く。この設定ウインドウではメモリーサイズや初期データの指定などをする。
まず「Memory Size」の「Width」を「4」、「Depth」を「18432」にする。これはメモリーサイズの指定で、今回は4ビット×18432(=384x192÷4)のメモリーを確保した。さらに今回は「Write Mode」を「No Read On Write」にした。設定が済んだら「Next」ボタンで次へ進む。

fpga_glcd_03_08.gif
ここではEnableやハンドシェイクなどの有無などを設定できる。今回はそのまま次へ進む。

fpga_glcd_03_09.gif
ここではクロックの立ち上がりを使うか立下りを見るかなどのタイミング設定ができる。ここもそのまま次へ進む。

fpga_glcd_03_10.gif
最後の画面ではメモリーの初期データの設定などができる。ここで画像データを初期データとして指定する。「Load Init File」にチェックを入れて、「Load File」ボタンを押す。

fpga_glcd_03_11.gif
するとファイル選択画面が開く。ここで用意した初期データのファイル「rom_data.coe」を選択する。

fpga_glcd_03_12.gif
用意した初期データはテキストファイルで、内容はこのようになっている。3行目から16進数でデータを並べている。今回はブロックRAMを4ビットとしたので、上位4ビットはゼロのままにしておく。



今回利用した初期データファイルをダウンロード


fpga_glcd_03_13.gif
初期データファイルの読み込みが終わったら、最後に「Generate」ボタンを押す。

fpga_glcd_03_14.gif
これで画面下部に「Generating IP...」と表示されてブロックRAMのデータが生成される。

fpga_glcd_03_15.gif
30秒程度すると「Finished Generating.」のように表示され、データ生成が終わるとともに左上の「Synthesis/Implementation」ウインドウ内に作成したブロックRAMを示す「ImageROM (ImageROM.xco)」という項目が追加される。

fpga_glcd_03_16.gif
さらにプロジェクトの保存されているフォルダを見ると複数のファイルが生成されている。このうち「ImageROM.vho」を開いてみると...

fpga_glcd_03_17.gif
生成したブロックRAMをVHDLで利用するためのテンプレートが用意されている。

fpga_glcd_03_18.gif
次に生成したブロックRAMデータを使って液晶パネルへのD信号を生成するためのソースコードを作る。「Project」メニューの「New Source」を選択する。

fpga_glcd_03_19.gif
そしてソースコードの形式から「VHDL Module」を選択しする。ファイル名は「GenerateD」とした。

fpga_glcd_03_20.gif
信号の設定画面では「CLK」、「CP」と「D」を用意し、それぞれ「in」、「in」、「out」に設定した。

fpga_glcd_03_21.gif
そしてソースコードが生成されたらブロックRAMのデータを用いてD信号を生成する。



----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 02:31:08 07/04/2007
-- Design Name:
-- Module Name: GenerateD - 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 GenerateD is
Port ( CLK : in STD_LOGIC;
CP : in STD_LOGIC;
D : out STD_LOGIC_VECTOR(3 downto 0));
end GenerateD;

architecture Behavioral of GenerateD is

component ImageROM
port (
addr: IN std_logic_VECTOR(14 downto 0);
clk: IN std_logic;
din: IN std_logic_VECTOR(3 downto 0);
dout: OUT std_logic_VECTOR(3 downto 0);
we: IN std_logic);
end component;


signal CLK_COUNT : STD_LOGIC_VECTOR(4 downto 0) := "00000"; --5bit for CP
signal ADDR : STD_LOGIC_VECTOR(14 downto 0) := "000000000000000";
signal DATA_IN : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal DATA_OUT : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal WE : STD_LOGIC;
signal CP_COUNT : STD_LOGIC_VECTOR(6 downto 0) := "0000000";

begin
WE <= '0'; --read only
DATA_IN <= "0000";

u1 : ImageROM
port map (
addr => ADDR,
clk => CLK,
din => DATA_IN,
dout => DATA_OUT,
we => WE);

process (CLK)
begin
if CLK'event and CLK='1' then
CLK_COUNT <= CLK_COUNT + "00001";
if CLK_COUNT = "00010" then
D <= DATA_OUT;
end if;
end if;
end process;

process (CP)
begin
if CP'event and CP='1' then
CP_COUNT <= CP_COUNT + "0000001";

if CP_COUNT = "1100011" then --99
CP_COUNT <= "0000000";
end if;

if CP_COUNT < "1100000" then --96(=100-4)
ADDR <= ADDR + "000000000000001";
end if;

if ADDR = "100011111111111" then --18431(=384x192/4-1)
ADDR <= "000000000000000";
end if;
end if;
end process;

end Behavioral;





fpga_glcd_03_22.gif
次にD信号を生成するためのソースコードを、これまでに作成したCPやLOADなどほかの信号と同期させる。左側のウインドウの「GenerateSignals - Behavioral (GenerateSignals.vhd)」をダブルクリックして開く。

fpga_glcd_03_23.gif
これまではD信号は固定値を指定していたが、先ほど作成したソースコードからの出力を使うように変える。


----------------------------------------------------------------------------------
-- 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;

component GenerateD
Port ( CLK : in STD_LOGIC;
CP : in STD_LOGIC;
D : out STD_LOGIC_VECTOR(3 downto 0));
end component;

begin

LOAD <= LOAD_TMP;
CP <= CP_TMP;
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);

u5: GenerateD port map(
CLK => CLOCK,
CP => CP_TMP,
D => D);

end Behavioral;





fpga_glcd_03_24.gif
これで一通りソースコードの修正が終わったのでFPGAに書き込むためのビットストリームファイルを作成する。「Generate Programming File」を右クリックして現れたメニューから「Run」を選択する。

fpga_glcd_03_25.gif
保存を問う画面が開いたら「OK」ボタンを押す。

fpga_glcd_03_26.gif
これで数分待つと論理合成などが終わりビットストリームファイルが生成される。

_DSC9186.JPG
これでFPGAへ書き込むとグラフィックス液晶モジュールに用意したビットマップデータが画像として表示された。今回用意したデータはISE WebPackのキャプチャー画像を2値化したものに、画像処理ソフトであとから線や文字を加えたデータになる。キャプチャー画像はやはり汚くはっきりとしないが、後から加えた線や文字はくっきりしている。この手の液晶パネルは表示するデータの用意が難しいなぁ。
この液晶は2値のものだが1秒間に異なるフレームを何回か表示すれば多階調表示することもできる。例えば4種類の画像を1秒間に3回ずつ表示すれば1ドット当たり16階調表示ができる...ということも考えられるが、こうすると用意するデータ量が増えてしまう。データ量が増えてもいいのであればカラー液晶を使った方が表現力が大きくていい。やはりせっかくモノクロ液晶を使うのだから2値表示を採用した方がいいかな。


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