FC2カウンター FPGAの部屋 Synthesijer でラプラシアンフィルタを作ってみた

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

FPGAの部屋

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

Synthesijer でラプラシアンフィルタを作ってみた

Synthesijer もひと通り、やってみたので、今度は”ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける”で使用した laplacian_filter.c のラプラシアンフィルタ部分のみのコードを Synthesijer でコンパイルすることにした。

ほとんど C のコードと同じだが、Java のコードに変更した laplacian_filter.java を下に示す。

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
public class laplacian_filter{
    public int lap_filter(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2){
        int y;

        y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
        if (y<0)
            y = 0;
        else if (y>255)
            y = 255;
        return(y);
    }
}


これを Make ファイルを修正して make した。Makefile の内の関係ある部分を下に示す。

SYNTHESIJER ?= ../../bin

SOURCES = laplacian_filter.java
VHDL_SOURCES = $(SOURCES:.java=.vhd)
VERILOG_SOURCES = $(SOURCES:.java=.v)

all: $(SOURCES)
    java -cp $(SYNTHESIJER) synthesijer.Main --verilog --vhdl $(SOURCES)


実行後に、laplacian_filter.vhd と laplacian_filter.v ファイルができた。

VHDLのテストベンチ (sim.vhd) を作製して、laplacian_filter.vhd をテストした。
GHDL + GTKWave では面倒なので、ModelSim AE 10.1e を使用した。
図 1 にシミュレーション結果を示す。
Synthesijer_15_141227.png
図 1 laplacian_filter.vhd のシミュレーション結果1 - 1

プロトコルを説明する。
lap_filter_req を 1 クロック間 1 にアサートした次のクロックで、lap_filter_busy が 1 にアサートされて計算中を示す。
lap_filter_busy が 0 にディアサートされた時が計算が終了した時で、この時には、lap_filter_return にラプラシアンフィルタの値が確定されている。
lap_filter_busy が 1 にアサートされた時から 0 にディアサートされるまでの幅は 240 ns だった。クロックは100MHz, 10 ns なので、ラプラシアンフィルタの計算に 24 クロックかかっている。
図 2 を見ると、unary_expr_0010 ~ binary_expr_0018 まで 1 クロックごとに 演算しているのがわかる。
Synthesijer_16_141227.png
図 2 laplacian_filter.vhd のシミュレーション結果1 - 2

lap_filter_req の間隔を狭めると (for i in 0 to 10 loop)、正しい値が出力できなくなる。その様子を図 3 に示す。
Synthesijer_17_141227.png
図 3 laplacian_filter.vhd のシミュレーション結果2

図 1 と図 2 のシミュレーション結果の sim.vhd を下に示す。

-- sim.vhd
-- Testbench for laplacian_filter.vhd 
-- 2014/12/27 by marsee

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity sim is
end sim;

architecture testbench of sim is
component laplacian_filter
  port (
    clk : in std_logic;
    reset : in std_logic;
    lap_filter_x0y0 : in signed(32-1 downto 0);
    lap_filter_x1y0 : in signed(32-1 downto 0);
    lap_filter_x2y0 : in signed(32-1 downto 0);
    lap_filter_x0y1 : in signed(32-1 downto 0);
    lap_filter_x1y1 : in signed(32-1 downto 0);
    lap_filter_x2y1 : in signed(32-1 downto 0);
    lap_filter_x0y2 : in signed(32-1 downto 0);
    lap_filter_x1y2 : in signed(32-1 downto 0);
    lap_filter_x2y2 : in signed(32-1 downto 0);
    lap_filter_req : in std_logic;
    lap_filter_busy : out std_logic;
    lap_filter_return : out signed(32-1 downto 0)
  );
end component;

constant clock_period : time := 10 ns;
constant delay : time := 1 ns;

signal clk : std_logic := '0';
signal reset : std_logic;
signal lap_filter_x0y0 : signed(32-1 downto 0);
signal lap_filter_x1y0 : signed(32-1 downto 0);
signal lap_filter_x2y0 : signed(32-1 downto 0);
signal lap_filter_x0y1 : signed(32-1 downto 0);
signal lap_filter_x1y1 : signed(32-1 downto 0);
signal lap_filter_x2y1 : signed(32-1 downto 0);
signal lap_filter_x0y2 : signed(32-1 downto 0);
signal lap_filter_x1y2 : signed(32-1 downto 0);
signal lap_filter_x2y2 : signed(32-1 downto 0);
signal lap_filter_req : std_logic;
signal lap_filter_busy : std_logic;
signal lap_filter_return : signed(32-1 downto 0);

begin
    clk <= not clk after clock_period/2; -- clk = 100MHz, 10 ns

    uut : laplacian_filter port map (
        clk                    => clk,
        reset                => reset,
        lap_filter_x0y0        => lap_filter_x0y0,
        lap_filter_x1y0        => lap_filter_x1y0,
        lap_filter_x2y0     => lap_filter_x2y0,
        lap_filter_x0y1     => lap_filter_x0y1,
        lap_filter_x1y1     => lap_filter_x1y1,
        lap_filter_x2y1     => lap_filter_x2y1,
        lap_filter_x0y2     => lap_filter_x0y2,
        lap_filter_x1y2     => lap_filter_x1y2,
        lap_filter_x2y2     => lap_filter_x2y2,
        lap_filter_req        => lap_filter_req,
        lap_filter_busy        => lap_filter_busy,
        lap_filter_return    => lap_filter_return
    );

    stimulus : process begin
        reset <= '1';
        lap_filter_x0y0 <= to_signed(0, 32);
        lap_filter_x1y0 <= to_signed(0, 32);
        lap_filter_x2y0 <= to_signed(0, 32);
        lap_filter_x0y1 <= to_signed(0, 32);
        lap_filter_x1y1 <= to_signed(0, 32);
        lap_filter_x2y1 <= to_signed(0, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);
        lap_filter_req <= '0';

        wait for 100 ns;
        reset <= '0';

        wait for 50 ns;

        lap_filter_x0y0 <= to_signed(127, 32);
        lap_filter_x1y0 <= to_signed(127, 32);
        lap_filter_x2y0 <= to_signed(127, 32);
        lap_filter_x0y1 <= to_signed(127, 32);
        lap_filter_x1y1 <= to_signed(127, 32);
        lap_filter_x2y1 <= to_signed(127, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);

        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '1';
        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '0';

        for i in 0 to 22 loop
            wait until clk'event and clk='1';
            wait for delay;
        end loop;

        lap_filter_x0y0 <= to_signed(127, 32);
        lap_filter_x1y0 <= to_signed(127, 32);
        lap_filter_x2y0 <= to_signed(127, 32);
        lap_filter_x0y1 <= to_signed(127, 32);
        lap_filter_x1y1 <= to_signed(81, 32);
        lap_filter_x2y1 <= to_signed(127, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);

        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '1';
        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '0';

        wait for 1 us;
        
        assert (false) report "Simulation End!" severity failure;
    end process;
end testbench;

  1. 2014年12月27日 19:47 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3023-134083ee
この記事にトラックバックする(FC2ブログユーザー)