// ラプラシアンフィルタ
// 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);
}
}
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)
-- 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;
を追加した。(jujurou さん、ありがとうございました)alias ls='ls --color=auto'
を書いた。set number
syntax on
java -cp C:\Users\Masaaki\Documents\Synthesijer\synthesijer-20141211.jar synthesijer.Main --vhdl --verilog^
Test.java ^
Top.java
set_property PACKAGE_PIN L16 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN R18 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN M14 [get_ports flag_return]
set_property IOSTANDARD LVCMOS33 [get_ports flag_return]
となるはずだ。125MHz / (5000001カウント * 7クロック * 2状態) ≒ 1.8 Hz
public class Test2{
public boolean flag;
private int count;
public void run(){
while(true){
if (count <= 10){
count++;
} else {
count = 0;
flag = !flag;
}
}
}
}
make.bat を実行すると、Test2.vhd と Test2.v ができる。java -cp C:\Users\Masaaki\Documents\Synthesijer\synthesijer-20141211.jar synthesijer.Main --vhdl --verilog^
Test2.java
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity Test2 is
port (
clk : in std_logic;
reset : in std_logic;
flag_in : in std_logic;
flag_we : in std_logic;
flag_out : out std_logic;
run_req : in std_logic;
run_busy : out std_logic
);
end Test2;
architecture RTL of Test2 is
signal clk_sig : std_logic;
signal reset_sig : std_logic;
signal flag_in_sig : std_logic;
signal flag_we_sig : std_logic;
signal flag_out_sig : std_logic;
signal run_req_sig : std_logic;
signal run_busy_sig : std_logic := '1';
signal class_flag_0000 : std_logic := '0';
signal class_flag_0000_mux : std_logic;
signal tmp_0001 : std_logic;
signal class_count_0001 : signed(32-1 downto 0) := (others => '0');
signal binary_expr_00002 : std_logic := '0';
signal unary_expr_00003 : signed(32-1 downto 0) := (others => '0');
signal unary_expr_00004 : std_logic := '0';
signal run_req_flag : std_logic;
signal run_req_local : std_logic := '0';
signal tmp_0002 : std_logic;
type Type_run_method is (
run_method_IDLE,
run_method_S_0000,
run_method_S_0001,
run_method_S_0002,
run_method_S_0003,
run_method_S_0004,
run_method_S_0005,
run_method_S_0006,
run_method_S_0007,
run_method_S_0008,
run_method_S_0009,
run_method_S_0010,
run_method_S_0012,
run_method_S_0013,
run_method_S_0014,
run_method_S_0015
);
signal run_method : Type_run_method := run_method_IDLE;
signal run_method_delay : signed(32-1 downto 0) := (others => '0');
signal tmp_0003 : std_logic;
signal tmp_0004 : std_logic;
signal tmp_0005 : std_logic;
signal tmp_0006 : std_logic;
signal tmp_0007 : std_logic;
signal tmp_0008 : signed(32-1 downto 0);
signal tmp_0009 : std_logic;
begin
clk_sig <= clk;
reset_sig <= reset;
flag_in_sig <= flag_in;
flag_we_sig <= flag_we;
flag_out <= flag_out_sig;
flag_out_sig <= class_flag_0000;
run_req_sig <= run_req;
run_busy <= run_busy_sig;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
run_busy_sig <= '1';
else
if run_method = run_method_S_0001 then
run_busy_sig <= run_req_flag;
end if;
end if;
end if;
end process;
-- expressions
tmp_0001 <= flag_in_sig when flag_we_sig = '1' else class_flag_0000;
tmp_0002 <= run_req_local or run_req_sig;
tmp_0003 <= '1' and '1';
tmp_0004 <= '1' and '0';
tmp_0005 <= '1' when binary_expr_00002 = '1' else '0';
tmp_0006 <= '1' when binary_expr_00002 = '0' else '0';
tmp_0007 <= '1' when class_count_0001 <= X"0000000a" else '0';
tmp_0008 <= class_count_0001 + X"00000001";
tmp_0009 <= not class_flag_0000;
-- sequencers
process (clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
run_method <= run_method_IDLE;
run_method_delay <= (others => '0');
else
case (run_method) is
when run_method_IDLE =>
run_method <= run_method_S_0000;
when run_method_S_0000 =>
run_method <= run_method_S_0001;
run_method <= run_method_S_0001;
when run_method_S_0001 =>
if run_req_flag = '1' then
run_method <= run_method_S_0002;
end if;
when run_method_S_0002 =>
if tmp_0003 = '1' then
run_method <= run_method_S_0004;
elsif tmp_0004 = '1' then
run_method <= run_method_S_0003;
end if;
when run_method_S_0003 =>
run_method <= run_method_S_0015;
when run_method_S_0004 =>
run_method <= run_method_S_0005;
when run_method_S_0005 =>
if tmp_0005 = '1' then
run_method <= run_method_S_0007;
elsif tmp_0006 = '1' then
run_method <= run_method_S_0010;
end if;
when run_method_S_0006 =>
run_method <= run_method_S_0014;
when run_method_S_0007 =>
run_method <= run_method_S_0008;
when run_method_S_0008 =>
run_method <= run_method_S_0009;
when run_method_S_0009 =>
run_method <= run_method_S_0006;
when run_method_S_0010 =>
run_method <= run_method_S_0012;
when run_method_S_0012 =>
run_method <= run_method_S_0013;
when run_method_S_0013 =>
run_method <= run_method_S_0006;
when run_method_S_0014 =>
run_method <= run_method_S_0002;
when run_method_S_0015 =>
run_method <= run_method_S_0000;
when others => null;
end case;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
class_flag_0000 <= '0';
else
if run_method = run_method_S_0012 then
class_flag_0000 <= unary_expr_00004;
else
class_flag_0000 <= class_flag_0000_mux;
end if;
end if;
end if;
end process;
class_flag_0000_mux <= tmp_0001;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
class_count_0001 <= (others => '0');
else
if run_method = run_method_S_0008 then
class_count_0001 <= unary_expr_00003;
elsif run_method = run_method_S_0010 then
class_count_0001 <= X"00000000";
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
binary_expr_00002 <= '0';
else
if run_method = run_method_S_0004 then
binary_expr_00002 <= tmp_0007;
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
unary_expr_00003 <= (others => '0');
else
if run_method = run_method_S_0007 then
unary_expr_00003 <= tmp_0008;
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
unary_expr_00004 <= '0';
else
if run_method = run_method_S_0010 then
unary_expr_00004 <= tmp_0009;
end if;
end if;
end if;
end process;
run_req_flag <= tmp_0002;
end RTL;
public class Test{
public boolean flag;
private int count;
public void run(){
while(true){
count++;
if(count > 10){
//if(count > 5000000){
count = 0;
flag = !flag;
}
}
}
}
となる。現在の動作クロックは 100MHz で 10 nsec なので、1カウント分の平均的なクロック数は800 /11 ≒ 72.7 nsec
となった。どうやら run_method_S_0011 の時に、flag_out が変化するようだ。ステートを遷移して行って判定を行いながら結果を出力しているのか?ユーザーズ・マニュアルが欲しいと思った。72.7 / 10 = 7.27 クロック
`default_nettype none
`timescale 1ns / 100ps
// Test_tb.v
// 2014/12/17
//
module Test_tb;
parameter DELAY = 1;
wire clk;
wire reset;
reg flag_in;
reg flag_we;
wire flag_out;
reg run_req;
wire run_busy;
Test uut_Test (
.clk(clk),
.reset(reset),
.flag_in(flag_in),
.flag_we(flag_we),
.flag_out(flag_out),
.run_req(run_req),
.run_busy(run_busy)
);
initial begin
// Initialize Inputs
flag_in <= 1'b0;
flag_we <= 1'b0;
run_req <= 1'b1;
end
// clk_gen のインスタンス(clk)
clk_gen #(
.CLK_PERIOD(10), // 10nsec, 100MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) ACLKi (
.clk_out(clk)
);
// reset_gen のインスタンス
reset_gen #(
.RESET_STATE(1'b1),
.RESET_TIME(100) // 100nsec
) RESET_ARESETN (
.reset_out(reset),
.init_done()
);
endmodule
module clk_gen #(
parameter CLK_PERIOD = 100,
parameter real CLK_DUTY_CYCLE = 0.5,
parameter CLK_OFFSET = 0,
parameter START_STATE = 1'b0 )
(
output reg clk_out
);
begin
initial begin
#CLK_OFFSET;
forever
begin
clk_out = START_STATE;
#(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
#(CLK_PERIOD*CLK_DUTY_CYCLE);
end
end
end
endmodule
module reset_gen #(
parameter RESET_STATE = 1'b1,
parameter RESET_TIME = 100 )
(
output reg reset_out,
output reg init_done
);
begin
initial begin
reset_out = RESET_STATE;
init_done = 1'b0;
#RESET_TIME;
reset_out = ~RESET_STATE;
init_done = 1'b1;
end
end
endmodule
`default_nettype wire
public class Test{
public boolean flag;
private int count;
public void run(){
while(true){
count++;
if(count > 5000000){
count = 0;
flag = !flag;
}
}
}
}
コマンドを実行すると Test.vhd ファイルを出力した。java -cp synthesijer-20141211.jar synthesijer.Main Test.java
ibrary IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity Test is
port (
clk : in std_logic;
reset : in std_logic;
flag_in : in std_logic;
flag_we : in std_logic;
flag_out : out std_logic;
run_req : in std_logic;
run_busy : out std_logic
);
end Test;
architecture RTL of Test is
signal clk_sig : std_logic;
signal reset_sig : std_logic;
signal flag_in_sig : std_logic;
signal flag_we_sig : std_logic;
signal flag_out_sig : std_logic;
signal run_req_sig : std_logic;
signal run_busy_sig : std_logic := '1';
signal class_flag_0000 : std_logic := '0';
signal class_flag_0000_mux : std_logic;
signal tmp_0001 : std_logic;
signal class_count_0001 : signed(32-1 downto 0) := (others => '0');
signal unary_expr_00002 : signed(32-1 downto 0) := (others => '0');
signal binary_expr_00003 : std_logic := '0';
signal unary_expr_00004 : std_logic := '0';
signal run_req_flag : std_logic;
signal run_req_local : std_logic := '0';
signal tmp_0002 : std_logic;
type Type_run_method is (
run_method_IDLE,
run_method_S_0000,
run_method_S_0001,
run_method_S_0002,
run_method_S_0003,
run_method_S_0004,
run_method_S_0005,
run_method_S_0006,
run_method_S_0007,
run_method_S_0008,
run_method_S_0009,
run_method_S_0011,
run_method_S_0012,
run_method_S_0013,
run_method_S_0014
);
signal run_method : Type_run_method := run_method_IDLE;
signal run_method_delay : signed(32-1 downto 0) := (others => '0');
signal tmp_0003 : std_logic;
signal tmp_0004 : std_logic;
signal tmp_0005 : std_logic;
signal tmp_0006 : std_logic;
signal tmp_0007 : signed(32-1 downto 0);
signal tmp_0008 : std_logic;
signal tmp_0009 : std_logic;
begin
clk_sig <= clk;
reset_sig <= reset;
flag_in_sig <= flag_in;
flag_we_sig <= flag_we;
flag_out <= flag_out_sig;
flag_out_sig <= class_flag_0000;
run_req_sig <= run_req;
run_busy <= run_busy_sig;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
run_busy_sig <= '1';
else
if run_method = run_method_S_0001 then
run_busy_sig <= run_req_flag;
end if;
end if;
end if;
end process;
-- expressions
tmp_0001 <= flag_in_sig when flag_we_sig = '1' else class_flag_0000;
tmp_0002 <= run_req_local or run_req_sig;
tmp_0003 <= '1' and '1';
tmp_0004 <= '1' and '0';
tmp_0005 <= '1' when binary_expr_00003 = '1' else '0';
tmp_0006 <= '1' when binary_expr_00003 = '0' else '0';
tmp_0007 <= class_count_0001 + X"00000001";
tmp_0008 <= '1' when class_count_0001 > X"004c4b40" else '0';
tmp_0009 <= not class_flag_0000;
-- sequencers
process (clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
run_method <= run_method_IDLE;
run_method_delay <= (others => '0');
else
case (run_method) is
when run_method_IDLE =>
run_method <= run_method_S_0000;
when run_method_S_0000 =>
run_method <= run_method_S_0001;
run_method <= run_method_S_0001;
when run_method_S_0001 =>
if run_req_flag = '1' then
run_method <= run_method_S_0002;
end if;
when run_method_S_0002 =>
if tmp_0003 = '1' then
run_method <= run_method_S_0004;
elsif tmp_0004 = '1' then
run_method <= run_method_S_0003;
end if;
when run_method_S_0003 =>
run_method <= run_method_S_0014;
when run_method_S_0004 =>
run_method <= run_method_S_0005;
when run_method_S_0005 =>
run_method <= run_method_S_0006;
when run_method_S_0006 =>
run_method <= run_method_S_0007;
when run_method_S_0007 =>
if tmp_0005 = '1' then
run_method <= run_method_S_0009;
elsif tmp_0006 = '1' then
run_method <= run_method_S_0008;
end if;
when run_method_S_0008 =>
run_method <= run_method_S_0013;
when run_method_S_0009 =>
run_method <= run_method_S_0011;
when run_method_S_0011 =>
run_method <= run_method_S_0012;
when run_method_S_0012 =>
run_method <= run_method_S_0008;
when run_method_S_0013 =>
run_method <= run_method_S_0002;
when run_method_S_0014 =>
run_method <= run_method_S_0000;
when others => null;
end case;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
class_flag_0000 <= '0';
else
if run_method = run_method_S_0011 then
class_flag_0000 <= unary_expr_00004;
else
class_flag_0000 <= class_flag_0000_mux;
end if;
end if;
end if;
end process;
class_flag_0000_mux <= tmp_0001;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
class_count_0001 <= (others => '0');
else
if run_method = run_method_S_0005 then
class_count_0001 <= unary_expr_00002;
elsif run_method = run_method_S_0009 then
class_count_0001 <= X"00000000";
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
unary_expr_00002 <= (others => '0');
else
if run_method = run_method_S_0004 then
unary_expr_00002 <= tmp_0007;
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
binary_expr_00003 <= '0';
else
if run_method = run_method_S_0006 then
binary_expr_00003 <= tmp_0008;
end if;
end if;
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
if reset = '1' then
unary_expr_00004 <= '0';
else
if run_method = run_method_S_0009 then
unary_expr_00004 <= tmp_0009;
end if;
end if;
end if;
end process;
run_req_flag <= tmp_0002;
end RTL;
オフセット0:コマンド・レジスタ(R/W)
ビット0:1 - LEDの値を+1する 0 - LEDの値はそのまま (デフォルト値は0)
ビット31~1:リザーブ
オフセット4:LED値のロード・レジスタ(R/W)
ビット7~0:8ビット分のLEDの値
ビット31~8:リザーブ(Read時はすべて0)オフセット8:現在のLEDの値のReadレジスタ(Read Only)(2014/12/16:AXI Lite Slave ウイザードだど実装が難しいので削除)
ビット7~0:8ビット分の現在のLEDの値
ビット31~8:すべて0
オフセットC:LED値を+1する時のカウント値(R/W)但し、動作クロックは100MHzとする
ビット31~0:LED値を+1する時のカウント値
#!/bin/sh
if [ $# -eq 1 ] ; then
gcc -ggdb `pkg-config --cflags opencv` -o `basename $1 .c` $1 `pkg-config --libs opencv`;
else
echo "gcc_opencv < C file name >"
fi
gcc_opencv と g++_opencv コマンドを実行形式に変更する。#!/bin/sh
if [ $# -eq 1 ] ; then
g++ -ggdb `pkg-config --cflags opencv` -o `basename $1 .cpp` $1 `pkg-config --libs opencv`;
else
echo "g++_opencv < C++ file name >"
fi
chmod +x gcc_opencv
chmod +x g++_opencv
export PATH=$PATH:~/OpenCV/bin
// laplacian_filter.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS 0x18200000 // 800*600*4 = 0x1d4c00
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);
int main()
{
volatile unsigned int *fb_addr, *next_frame_addr;
int lap_fil_val;
int x, y;
struct timeval start_time, temp1, temp2, end_time;
unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
int a, b;
int fl, sl, tl;
int fd0, fd3;
volatile unsigned *bmdc_axi_lites;
volatile unsigned int *frame_buffer;
gettimeofday(&start_time, NULL); // プログラム起動時の時刻を記録
// frame_buffer にマップする
fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
fb_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));
// ラプラシアンフィルタの結果を入れておくフレーム・バッファ
next_frame_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
lap_fil_val = 0;
}else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
lap_fil_val = 0;
}else{
if (y == 1 && x == 1){ // 最初のラインの最初のピクセルでは2ライン分の画素を読み出す
for (a=0; a<2; a++){ // 2ライン分
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
line_buf[a][b] = fb_addr[(a*HORIZONTAL_PIXEL_WIDTH)+b];
line_buf[a][b] = conv_rgb2y(line_buf[a][b]);
}
}
}
if (x == 1) { // ラインの最初なので、2つのピクセルを読み込む
for (b=0; b<2; b++){ // ライン
line_buf[(y+1)%3][b] = fb_addr[((y+1)*HORIZONTAL_PIXEL_WIDTH)+b];
// (y+1)%3 は、使用済みのラインがに読み込む、y=2 の時 line[0], y=3の時 line[1], y=4の時 line[2]
line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]);
}
}
// 1つのピクセルを読み込みながらラプラシアン・フィルタを実行する
line_buf[(y+1)%3][x+1] = fb_addr[((y+1)*HORIZONTAL_PIXEL_WIDTH)+x];
// (y+1)%3 は、使用済みのラインがに読み込む、y=2 の時 line[0], y=3の時 line[1], y=4の時 line[2]
line_buf[(y+1)%3][x+1] = conv_rgb2y(line_buf[(y+1)%3][x+1]);
fl = (y-1)%3; // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
sl = y%3; // 2番めのライン
tl = (y+1)%3; // 3番目のライン
lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
}
// ラプラシアンフィルタ・データの書き込み
next_frame_addr[(y*HORIZONTAL_PIXEL_WIDTH)+x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val ;
// printf("x = %d y = %d", x, y);
}
}
munmap((void *)frame_buffer, 0x1000000);
// ラプラシアンフィルタ表示画面に切り替え
// Bitmap Display Controller AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 open error\n");
exit(-1);
}
bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!bmdc_axi_lites){
fprintf(stderr, "bmdc_axi_lites mmap error\n");
exit(-1);
}
bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
munmap((void *)bmdc_axi_lites, 0x10000);
gettimeofday(&end_time, NULL);
if (end_time.tv_usec < start_time.tv_usec) {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec);
}
else {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
}
return(0);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(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);
}
// 文字列が16進数かを調べる
int chkhex(char *str){
while (*str != '\0'){
if (!isxdigit(*str))
return 0;
str++;
}
return 1;
}
//
// return_cam.c
// Created on: 2014/12/05
// Author: Masaaki
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS 0x18200000 // 800*600*4 = 0x1d4c00
int main(){
int fd0;
volatile unsigned *bmdc_axi_lites;
// Bitmap Display Controller AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 open error\n");
exit(-1);
}
bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!bmdc_axi_lites){
fprintf(stderr, "bmdc_axi_lites mmap error\n");
exit(-1);
}
bmdc_axi_lites[0] = (unsigned int)VIDEO_BUFFER_START_ADDRESS; // Bitmap Display Controller start, camera display
munmap((void *)bmdc_axi_lites, 0x10000);
}
Vivado and ZYBO Linux 勉強会 基本方針
1日目
午前
・Zynq-7000の概要
・Vivadoツールの概要
午後
・LEDテストプロジェクトをライブコーディング(VivadoのウィザードでAXIカスタムIPを作る)
IPをわざと間違えておいて、IPの修正方法を実習する
2日目
午前・午後 ハンズオン
・ハードウェアは、1日目のVivadoプロジェクトを使用する
・ZYBO用u-bootのビルド
・SDKでBoot.bin を作製
・ZYBO用Linuxカーネルのビルド
・デバイス・ツリーのコンパイル
・Micro SDカードのフォーマット
・UbuntuのROOT File Systemのコピー
・FAT32パーティションへ必要なファイルをコピー
・ZYBOにSDカードを挿してLinuxをブート
・ユーザーでログイン
・LEDをカウントアップするソフトウェアを実行(UIOの実習)
・SSHのインストール
・XmingでXウインドウをWindowsで操作
・OpenCVインストール
・サンプル・プロジェクトのコンパイル
・顔認識アプリの実行
”SSHのインストール”からはルーターが必要になるし、時間も足りなくなりそうなので、”LEDをカウントアップするソフトウェアを実行(UIOの実習)”までなかな?と思っています。
VivadoはネイティブLinuxノートパソコンか、VirtualBoxへインストールしたLinuxでやろうかと思っています。そうでないと、ARM用のGCCがインストールされないようなので。
Vivado をWindowsで使いたい方は、Menter社 のSourcery CodeBench Lite Editionを使う方法もあります。
この辺りは現在検討中です。
VivadoツールとLinux環境は予めインストールをお願いする予定です。
source /opt/Xilinx/Vivado/2014.4/settings64.sh
だった。/bin/sh: 1: arm-xilinx-eabi-gcc: not found
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | - | - | - |