目次
前
次
VHDLコード改造
日常生活に復帰してから、VHDLコードを見直しました。
改造すべき内容は、次の3項目です。
- PCLKに同期して画像データ入力
- 2値化したデータを1ビット単位で処理
- 動作クロック逓倍
1項目に1週間かけ、丹念に改造していきます。
画像データ入力改造
画像データをPCLKに同期して入力するように変更します。
PCLKは、一度バッファに入れてから
シーケンサにクロックとして与えます。
iPCLK <= PCLK ;
iHREF <= HREF ;
PCLKは、OV7670からVSYNC、HREFを出力するための
トリガーであり、データのラッチタイミングとして
使うので、rising_edgeを利用してシーケンサを
動かします。
タイミングチャートを見ながら、水平と垂直に分けて
処理を考えてみます。
水平処理はHREFが'H'のときに、データを保存。
このデータは2バイトで1ピクセルなので
16ビットのレジスタを用意し、8ビットずつ
2回データを保存する。
この方式を、次のVHDLコードで実現します。
PCNTは、ピクセルカウンタとします。
process (nRESET,iPCLK)
begin
if ( nRESET = '0' ) then
iCDATA <= (others => '0') ;
iPCNT <= (others => '0') ;
elsif rising_edge(iPCLK) then
-- store data
if ( iHREF = '1' ) then
iCDATA <= iCDATA(7 downto 0) & CDAT ;
iPCNT <= iPCNT + 1 ;
end if ;
-- judge
if ( conv_integer(iPCNT) = PCNT_MAX2 ) then
iPCNT <= (others => '0') ;
end if ;
end if ;
end process ;
輝度信号は、16ビットデータの上位に含まれるので
画像データとしてメモリ保存するには、上位8ビット
をコピーして、DualPortMemoryに転送することに。
ピクセルカウンタは、320になったならゼロクリアし
次の動作に備えます。
画像データを指定ラインで処理したいので、垂直方向
では、ラインカウンタを用意して、動作を考えます。
タイミングチャートを見ていきます。
垂直方向はVSYNCが'L'→'H'となるときをトリガーにし
シーケンサを動かします。HREFが'L'→'H'となるとき
ラインカウンタを増やします。
VSYNC、HREFの変化をとらえるには、PCLKよりも高速な
クロックで動くシフトレジスタを使えばよいはず。
iCLKFX_OUTがPCLKよりも、高速なクロックとすると
次のVHDLコードで、変化をトリガーにします。
(iCLKFX_OUTは、後で考えます。)
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iVS_SFT <= "000" ;
iHREF_SFT <= "000" ;
elsif rising_edge(iCLKFX_OUT) then
iVS_SFT <= iVS_SFT(1 downto 0) & VS ;
iHREF_SFT <= iHREF_SFT(1 downto 0) & iHREF ;
end if ;
end process ;
iVSTRG <= '1' when ( iVS_SFT = "011" or iVS_SFT = "001" ) else '0' ;
iHREF_TRG <= '1' when ( iHREF_SFT = "011" or iHREF_SFT = "001" ) else '0' ;
画像データは、マイコンからの指示でメモリに
保存したいため、VSYNC、HREFのトリガーにより
ラインカウンタを増やしていきます。シーケンサ
は、次のように定義します。
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iCSTATE <= "000" ;
-- line counter
iLCNT <= 0 ;
elsif rising_edge(iCLKFX_OUT) then
case conv_integer(iCSTATE) is
-- wait trigger from micro computer
when 0 => if ( iCTRG = '1' ) then
iCSTATE <= "001" ; -- next
else
iCSTATE <= "000" ; -- stay
end if ;
-- wait VSYNC trigger
when 1 => if ( iVSTRG = '1' ) then
iCSTATE <= "011" ; -- next
else
iCSTATE <= "001" ; -- stay
end if ;
-- wait HREF_TRG
when 3 => if ( iHREF_TRG = '1' ) then
iCSTATE <= "111" ; -- next
else
iCSTATE <= "011" ; -- stay
end if ;
-- line counter increment
when 7 => iCSTATE <= "110" ; -- next
iLCNT <= iLCNT + 1 ;
-- judge line counter is last value
when 6 => if ( iLCNT = LCNT_MAX ) then
iCSTATE <= "100" ; -- exit loop
else
iCSTATE <= "011" ; -- loop
end if ;
-- return first state
when 4 => iCSTATE <= "000" ;
-- clear line counter
iLCNT <= 0 ;
-- default
when others =>
iCSTATE <= "000" ;
end case ;
end if ;
end process ;
-- enable graphic data store
iSTORE_FLAG <= iCSTATE(1) or iCSTATE(0) ;
-- binary conversion (trigger)
iBTRG <= '1' when ( iCSTATE = "100" ) else '0' ;
マイコンから与えられるトリガーを起点として
VSYNCのトリガー確認後、HREFのトリガーにより
カウンタが+1していきます。
ラインカウンタが出来たので、どのラインで画像データ
を保存するのかをフラグで指定できるようになりました。
3ラインの指定をフラグで定義すると、以下。
iTARGET_LTMB <= iTARGET_LT or iTARGET_LM or iTARGET_LB ;
iTARGET_LA <= iTARGET_LTMB and iSTORE_FLAG ;
iTARGET_LT <= '1' when ( iLCNT = conv_integer(iTLTOP) ) else '0' ;
iTARGET_LM <= '1' when ( iLCNT = conv_integer(iTLMIDDLE) ) else '0' ;
iTARGET_LB <= '1' when ( iLCNT = conv_integer(iTLBOTTOM) ) else '0' ;
ライン、ピクセルのカウンタができたので
メモリに画像データを格納するための動作
を考えます。
ピクセルカウンタが偶数のときに、画像データを
バッファレジスタに転送します。
カウンタが偶数のときに、トリガーを出力する
回路を定義します。
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iPCNTX <= (others => '0') ;
elsif rising_edge(iCLKFX_OUT) then
-- shift
iPCNTX <= iPCNTX(8 downto 0) & iPCNT ;
end if ;
end process ;
-- previous != current and current LSB = 0
iPCNT_TRG <= '1' when ( iPCNTX(17 downto 9) /= iPCNTX(8 downto 0) and iPCNT(0) = '0' ) else '0' ;
ピクセルカウンタをシフトレジスタに転送し
ひとつ前と現在の値が異なって、現在の値が
偶数のときに、トリガーを出力します。
このトリガーiPCNT_TRGを利用し、メモリへ
データを保存するシーケンサを定義します。
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iASTATE <= 0 ;
-- dual port memory address
iCADRA <= (others => '0') ;
-- maximum
iTMAX <= (others => '0') ;
iMMAX <= (others => '0') ;
iBMAX <= (others => '0') ;
-- minimum
iTMIN <= (others => '1') ;
iMMIN <= (others => '1') ;
iBMIN <= (others => '1') ;
-- threshold
iTHVT <= 128 ;
iTHVM <= 128 ;
iTHVB <= 128 ;
elsif rising_edge(iCLKFX_OUT) then
case iASTATE is
-- wait store trigger
when 0 => if ( iPCNT_TRG = '1' ) then
iASTATE <= 1 ; -- next
else
iASTATE <= 0 ; -- stay
end if ;
-- get Y signal data
when 1 => iASTATE <= 2 ; -- next
iCYDAT <= iCDATA(15 downto 8) ;
-- judge store or skip
when 2 => if ( iTARGET_LA = '1' ) then
iASTATE <= 3 ; -- store
else
iASTATE <= 6 ; -- skip
end if ;
-- copy Y signal
when 3 => iASTATE <= 4 ; -- next
iDIA <= iCYDAT ;
-- store Y signal to dual port memory
-- update maximum and mininum
when 4 => iASTATE <= 5 ; -- next
-- TOP
if ( iTARGET_LT = '1' ) then
-- maximum
if ( conv_integer(iTMAX) < conv_integer(iCYDAT) ) then
iTMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iTMIN) > conv_integer(iCYDAT) ) then
iTMIN <= iCYDAT ;
end if ;
end if ;
-- MIDDLE
if ( iTARGET_LM = '1' ) then
-- maximum
if ( conv_integer(iMMAX) < conv_integer(iCYDAT) ) then
iMMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iMMIN) > conv_integer(iCYDAT) ) then
iMMIN <= iCYDAT ;
end if ;
end if ;
-- BOTTOM
if ( iTARGET_LB = '1' ) then
-- maximum
if ( conv_integer(iBMAX) < conv_integer(iCYDAT) ) then
iBMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iBMIN) > conv_integer(iCYDAT) ) then
iBMIN <= iCYDAT ;
end if ;
end if ;
-- address increment (dual port memory)
when 5 => iASTATE <= 6 ; -- next
if ( iTARGET_LTMB = '1' ) then
iCADRA <= iCADRA + 1 ;
end if ;
-- judge
when 6 => if ( iCADRA = QMAX ) then
iASTATE <= 7 ; -- exit loop
else
iASTATE <= 0 ; -- loop
end if ;
-- calculate
when 7 => iASTATE <= 8 ; -- next
-- threshold
iTHVT <= (conv_integer(iTMAX) + conv_integer(iTMIN)) / 2 ;
iTHVM <= (conv_integer(iMMAX) + conv_integer(iMMIN)) / 2 ;
iTHVB <= (conv_integer(iBMAX) + conv_integer(iBMIN)) / 2 ;
-- prepare next stage
when 8 => iASTATE <= 9 ; -- next
-- dual port memory address
iCADRA <= (others => '0') ;
-- maximum
iTMAX <= (others => '0') ;
iMMAX <= (others => '0') ;
iBMAX <= (others => '0') ;
-- minimum
iTMIN <= (others => '1') ;
iMMIN <= (others => '1') ;
iBMIN <= (others => '1') ;
-- return first state
when 9 => iASTATE <= 0 ;
-- default
when others =>
iASTATE <= 0 ;
end case ;
end if ;
end process ;
-- store Y data to camera buffer (trigger)
iWEA <= '1' when ( iASTATE = 4 ) else '0' ;
画像データを保存しながら、ラインごとの最大値、最小値を
求めてから、2値化するための閾値を計算します。
処理を終了するのは、160ピクセルx3ライン分の
データをメモリに格納したときにしました。
目的のデータを上書きしないように、バッファレジスタ
を使い、複写を作って対応します。
1ビット単位処理
画像データは8ビット単位で、カメラデータ用
DualPortMemoryに保存します。
2値化すると1ビットになるので、DualPortMemoryを
1ビットごとにアドレスをつけることに。
16kx1ビットの入力、出力にして定義します。
DualPortMemoryの定義は以下です。
XBUFX : RAMB16_S1_S1
generic map (
INIT_A => "0", -- Value of output RAM registers on Port A at startup
INIT_B => "0", -- Value of output RAM registers on Port B at startup
SRVAL_A => "0", -- Port A ouput value upon SSR assertion
SRVAL_B => "0", -- Port B ouput value upon SSR assertion
WRITE_MODE_A => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
WRITE_MODE_B => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL"
-- The following INIT_xx declarations specify the initial contents of the RAM
-- Address 0 to 4095
INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 4096 to 8191
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 8192 to 12287
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 12288 to 16383
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
port map (
DOA => open, -- Port A 1-bit Data Output
DOB => iBDOB, -- Port B 1-bit Data Output
ADDRA => iBADRA, -- Port A 14-bit Address Input
ADDRB => iBADRB, -- Port B 14-bit Address Input
CLKA => iCLKFX_OUT, -- Port A Clock
CLKB => iCLKFX_OUT, -- Port B Clock
DIA => iBDIA, -- Port A 1-bit Data Input
DIB => "0", -- Port B 1-bit Data Input
ENA => '1', -- Port A RAM Enable Input
ENB => '0', -- PortB RAM Enable Input
SSRA => '0', -- Port A Synchronous Set/Reset Input
SSRB => '0', -- Port B Synchronous Set/Reset Input
WEA => iBWEA, -- Port A Write Enable Input
WEB => '0' -- Port B Write Enable Input
);
カメラからの画像データをDualPortMemoryにデータを
保存するとき、閾値を求めているので、1ビット変換
後、定義した別のDualPortMemoryに保存します。
シーケンサは、次のように定義しました。
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iBSTATE <= 0 ;
-- address
iCADRB <= (others => '0') ; -- camera buffer
iBADRA <= (others => '0') ; -- binary code buffer
-- data
iBDAT <= (others => '0') ; -- camera buffer data
iBDIA <= (others => '0') ; -- binary code
-- measure flag
iBFLAG <= 0 ;
elsif rising_edge(iCLKFX_OUT) then
case conv_integer(iBSTATE) is
-- wait trigger
when 0 => if ( iBTRG = '1' ) then
iBSTATE <= 1 ; -- next
-- initialize address
iCADRB <= (others => '0') ; -- camera buffer
iBADRA <= (others => '0') ; -- binary code
else
iBSTATE <= 0 ; -- stay
end if ;
-- initialize
when 1 => iBSTATE <= 2 ; -- next
iBCNT <= 0 ;
-- get data from camera buffer
when 2 => iBSTATE <= 3 ; -- next
iBDAT <= iDOB ;
iBCNT <= iBCNT + 1 ; -- increment counter
-- camera buffer address increment
when 3 => iBSTATE <= 4 ; -- next
iCADRB <= iCADRB + 1 ;
iBDIA <= "0" ;
-- compare
when 4 => iBSTATE <= 5 ; -- next
-- TOP
if ( iBFLAG = 0 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVT) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- MIDDLE
if ( iBFLAG = 1 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVM) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- BOTTOM
if ( iBFLAG = 2 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVB) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- store
when 5 => iBSTATE <= 6 ; -- next
-- binary data address increment
when 6 => iBSTATE <= 7 ; -- next
iBADRA <= iBADRA + '1' ;
-- judge
when 7 => if ( iBCNT = PCNT_MAX ) then
iBSTATE <= 8 ; -- next
else
iBSTATE <= 2 ; -- loop
end if ;
-- flag increment
when 8 => iBSTATE <= 9 ; -- next
iBFLAG <= iBFLAG + 1 ; -- update
iBCNT <= 0 ;
-- judge
when 9 => if ( iBFLAG = 3 ) then
iBSTATE <= 10 ; -- exit
else
iBSTATE <= 1 ; -- loop
end if ;
-- complete and send trigger
when 10 => iBSTATE <= 11 ; -- next
iBFLAG <= 0 ; -- clear flag
-- return first state
when 11 => iBSTATE <= 0 ; -- first state
-- default
when others =>
iBSTATE <= 0 ;
end case ;
end if ;
end process ;
-- binary data store trigger
iBWEA <= '1' when ( iBSTATE = 5 ) else '0' ;
-- generate parameters trigger
iLTRG <= '1' when ( iBSTATE = 10 ) else '0' ;
2値化するときに使う閾値が異なるので
計数フラグiBFLAGを使い切り替えます。
2値化が終了したならば、センサーデータの
関係情報を生成するシーケンサを起動します。
動作クロック逓倍
画像データをPCLKに同期して入力する方式に変更した
ので、他の処理は入力クロックを逓倍して処理します。
XilinxのFPGAには、DCM(Digital Clock Module)が含まれ
DFS(Digital Frequency Synchoronizer)を使い、入力した
周波数を逓倍してから、クロックとして使えます。
DFSで、FPGAに入力されているクロック20MHzを逓倍して
40MHzにしてから、内部回路を動かすことに。
DCMは、次のようにクロックバッファを入れて使います。
実際に利用したDCMの定義は、以下です。
DCM_inst : DCM
generic map (
CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
-- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
CLKFX_DIVIDE => 1, -- Can be any integer from 1 to 32
CLKFX_MULTIPLY => 2, -- Can be any integer from 2 to 32
CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature
CLKIN_PERIOD => 50.0, -- Specify period of input clock
CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift of NONE, FIXED or VARIABLE
CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE, 1X or 2X
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
-- an integer from 0 to 15
DFS_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for frequency synthesis
DLL_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for DLL
DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE
FACTORY_JF => X"C080", -- FACTORY JF Values
PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 255
SIM_MODE => "SAFE", -- Simulation: "SAFE" vs "FAST", see "Synthesis and Simulation
-- Design Guide" for details
STARTUP_WAIT => FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
port map (
CLK0 => iCLK0_OUT, -- 0 degree DCM CLK ouptput
CLK180 => open, -- 180 degree DCM CLK output
CLK270 => open, -- 270 degree DCM CLK output
CLK2X => open, -- 2X DCM CLK output
CLK2X180 => open, -- 2X, 180 degree DCM CLK out
CLK90 => open, -- 90 degree DCM CLK output
CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE)
CLKFX => iCLKFX, -- DCM CLK synthesis out (M/D)
CLKFX180 => open, -- 180 degree CLK synthesis out
LOCKED => open, -- DCM LOCK status output
PSDONE => open, -- Dynamic phase adjust done output
STATUS => open, -- 8-bit DCM status bits output
CLKFB => iCLKFB_IN, -- DCM clock feedback
CLKIN => iCLKIN_IBUFG, -- Clock input (from IBUFG, BUFG or DCM)
PSCLK => '0', -- Dynamic phase adjust clock input
PSEN => '0', -- Dynamic phase adjust enable input
PSINCDEC => '0', -- Dynamic phase adjust increment/decrement
RST => '0' -- DCM asynchronous reset input
);
DCMから出力されるクロックを、バッファに入れてから
FPGA内部に分配すると、クロックスキューがなくなり
開発環境が出していたWaringもなくなりました。
全ソースコード
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity mcrvcxy is
generic (
TOPX : integer := 11 ;
XMAX : integer := 2000 ;
TOPY : integer := 5 ;
YMAX : integer := 25 ;
TOPU : integer := 5 ;
UMAX : integer := 25 ;
LCNT_MAX : integer := 60 ;
PCNT_MAX : integer := 160 ;
PCNT_MAX2 : integer := 320 ;
QMAX : integer := 480 --; 160pixel x 3line
);
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- camera interface
VS : in std_logic ;
HREF : in std_logic ;
PCLK : in std_logic ;
CDAT : in std_logic_vector(7 downto 0) ;
-- run output
GLED : out std_logic ; -- rotary encoder pulse monitor
RLED : out std_logic ; -- run
-- MOTOR control
FOUT : out std_logic_vector(1 downto 0) ;
ROUT : out std_logic_vector(1 downto 0) ;
-- encoder
ENPULSE : in std_logic ;
-- monitor
STATEX : out std_logic_vector(3 downto 0) ;
ATRGX : out std_logic ;
BTRGX : out std_logic ;
WTRGX : out std_logic ;
MVS : out std_logic ;
HPCLK : out std_logic ;
XMOUT : out std_logic_vector(3 downto 0) ;
XMOUTSEL : in std_logic_vector(1 downto 0) ;
-- BUS interface control signals
GP2 : in std_logic_vector(7 downto 0) ;
-- CENA
-- TRG
-- WE
-- OE
-- LSEL3
-- LSEL2
-- LSEL1
-- LSEL0
-- BUS interface
GP3 : inout std_logic_vector(7 downto 0) --;
);
end mcrvcxy;
architecture Behavioral of mcrvcxy is
-- component clock generator
component clkgenx is
generic (
TOPX : integer ;
RMAX : integer --;
);
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- output
CLKOUT : out std_logic -- ;
);
end component ;
-- component PWM
component pwmax is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- input
DIR : in std_logic_vector(1 downto 0) ;
-- duty ratio
DUTY : in std_logic_vector(6 downto 0) ;
-- output
POUT : out std_logic_vector(1 downto 0) --;
);
end component;
-- clock (DCM)
signal iCLK0_OUT : std_logic ;
signal iCLKFX : std_logic ;
signal iCLKFB_IN : std_logic ;
signal iCLKIN_IBUFG : std_logic ;
signal iCLKFX_OUT : std_logic ;
-- clock
signal iPWMCLK : std_logic ;
signal iSCLK : std_logic ;
signal iICLK : std_logic ;
signal iPCLK : std_logic ;
-- camera sequencer
signal iCSTATE : std_logic_vector(2 downto 0) ;
signal iSTORE_FLAG : std_logic ;
signal iCSTATEX : std_logic_vector(3 downto 0) ;
signal iLCNT : integer range 0 to LCNT_MAX ;
signal iPCNT : std_logic_vector( 8 downto 0) ;
signal iPCNTX : std_logic_vector(17 downto 0) ;
signal iPCNT_TRG : std_logic ;
signal iCDATA : std_logic_vector(15 downto 0) ;
signal iCTRG : std_logic ;
signal iVSTRG : std_logic ;
signal iHREF : std_logic ;
signal iHREF_SFT : std_logic_vector(2 downto 0) ;
signal iHREF_TRG : std_logic ;
signal iCTRG_SFT : std_logic_vector(2 downto 0) ;
signal iVS_SFT : std_logic_vector(2 downto 0) ;
-- camera data store sequencer
signal iASTATE : integer range 0 to 9 ;
signal iCYDAT : std_logic_vector( 7 downto 0) ;
signal iTARGET_LA : std_logic ;
signal iTARGET_LT : std_logic ;
signal iTARGET_LM : std_logic ;
signal iTARGET_LB : std_logic ;
signal iTARGET_LTMB : std_logic ;
signal iTMAX : std_logic_vector(7 downto 0) ;
signal iTMIN : std_logic_vector(7 downto 0) ;
signal iMMAX : std_logic_vector(7 downto 0) ;
signal iMMIN : std_logic_vector(7 downto 0) ;
signal iBMAX : std_logic_vector(7 downto 0) ;
signal iBMIN : std_logic_vector(7 downto 0) ;
signal iTHVT : integer range 0 to 255 ;
signal iTHVM : integer range 0 to 255 ;
signal iTHVB : integer range 0 to 255 ;
-- camera buffer memory
signal iCADRA : std_logic_vector(10 downto 0) ;
signal iCADRB : std_logic_vector(10 downto 0) ;
signal iDIA : std_logic_vector( 7 downto 0) ;
signal iDOB : std_logic_vector( 7 downto 0) ;
signal iWEA : std_logic ;
signal iBTRG : std_logic ;
-- buffer memory
signal iBADRA : std_logic_vector(13 downto 0) ;
signal iBADRB : std_logic_vector(13 downto 0) ;
signal iBDIA : std_logic_vector(0 downto 0) ;
signal iBDOB : std_logic_vector(0 downto 0) ;
signal iBWEA : std_logic ;
-- store binary data sequencer
signal iBCNT : integer range 0 to 160 ;
signal iBDAT : std_logic_vector(7 downto 0) ;
signal iBFLAG : integer range 0 to 3 ;
signal iBSTATE : integer range 0 to 11 ;
-- last sequencer
signal iLTRG : std_logic ;
signal iLSTATE : integer range 0 to 9 ;
signal iWCNT : integer range 0 to PCNT_MAX ;
signal iWNOW : integer range 0 to 255 ;
signal iWNEXT : integer range 0 to 255 ;
signal iWFLAG : integer range 0 to 3 ;
signal iWZP : integer range 0 to 255 ;
signal iWPZ : integer range 0 to 255 ;
-- MOTOR control
signal iFOUT : std_logic_vector(1 downto 0) ;
signal iROUT : std_logic_vector(1 downto 0) ;
-- BUS interface
signal iDIRR : std_logic_vector(1 downto 0) ;
signal iDIRF : std_logic_vector(1 downto 0) ;
signal iDUTYF : std_logic_vector(6 downto 0) ;
signal iDUTYR : std_logic_vector(6 downto 0) ;
signal iDSTATE : std_logic_vector(1 downto 0) ;
signal iDADR : std_logic_vector(3 downto 0) ;
signal iDDAT : std_logic_vector(7 downto 0) ;
-- trigger
signal iTRG : std_logic ;
signal iTRG_SFT : std_logic_vector(2 downto 0) ;
-- sensor register file (location)
signal iDAT : std_logic_vector(7 downto 0) ;
signal iLTOP : std_logic_vector(7 downto 0) ;
signal iLMIDDLE : std_logic_vector(7 downto 0) ;
signal iLBOTTOM : std_logic_vector(7 downto 0) ;
-- sensor register file (distance)
signal iLTOPD : std_logic_vector(7 downto 0) ;
signal iLMIDDLED : std_logic_vector(7 downto 0) ;
signal iLBOTTOMD : std_logic_vector(7 downto 0) ;
-- target line register file
signal iTLTOP : std_logic_vector(7 downto 0) ;
signal iTLMIDDLE : std_logic_vector(7 downto 0) ;
signal iTLBOTTOM : std_logic_vector(7 downto 0) ;
-- encoder counter
signal iECNT : std_logic_vector(15 downto 0) ;
signal iECNTX : std_logic_vector(15 downto 0) ;
signal iENPLS_SFT : std_logic_vector( 2 downto 0) ;
signal iENPLS : std_logic ;
signal iSETPLS : std_logic ;
begin
-- component clock generator (20MHz/4000 = 5kHz)
CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,iCLKFB_IN,iPWMCLK);
-- component clock generator (5kHz/50 = 100Hz)
CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iPWMCLK,iSCLK);
-- component clock generator (100Hz/50 = 2Hz)
CLKU : clkgenx generic map (TOPU,UMAX) port map (nRESET,iSCLK,iICLK);
-- front motor control
FRONTX : pwmax port map (nRESET,iPWMCLK,iDIRF,iDUTYF,iFOUT);
-- rear motor control
REARX : pwmax port map (nRESET,iPWMCLK,iDIRR,iDUTYR,iROUT);
-- input clock buffer handling
IBUFG_inst : IBUFG
generic map (IOSTANDARD => "DEFAULT")
port map (
O => iCLKIN_IBUFG, -- Clock buffer output
I => CLOCK -- Clock buffer input (connect directly to top-level port)
);
-- output clock buffer handling
BUFG_inst : BUFG
port map (
O => iCLKFB_IN, -- Clock buffer output
I => iCLK0_OUT -- Clock buffer input
);
-- output clock buffer handling
BUFG_instX : BUFG
port map (
O => iCLKFX_OUT , -- Clock buffer output
I => iCLKFX -- Clock buffer input
);
-- DCM
DCM_inst : DCM
generic map (
CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
-- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
CLKFX_DIVIDE => 1, -- Can be any integer from 1 to 32
CLKFX_MULTIPLY => 2, -- Can be any integer from 2 to 32
CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature
CLKIN_PERIOD => 50.0, -- Specify period of input clock
CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift of NONE, FIXED or VARIABLE
CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE, 1X or 2X
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
-- an integer from 0 to 15
DFS_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for frequency synthesis
DLL_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for DLL
DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE
FACTORY_JF => X"C080", -- FACTORY JF Values
PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 255
SIM_MODE => "SAFE", -- Simulation: "SAFE" vs "FAST", see "Synthesis and Simulation
-- Design Guide" for details
STARTUP_WAIT => FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
port map (
CLK0 => iCLK0_OUT, -- 0 degree DCM CLK ouptput
CLK180 => open, -- 180 degree DCM CLK output
CLK270 => open, -- 270 degree DCM CLK output
CLK2X => open, -- 2X DCM CLK output
CLK2X180 => open, -- 2X, 180 degree DCM CLK out
CLK90 => open, -- 90 degree DCM CLK output
CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE)
CLKFX => iCLKFX, -- DCM CLK synthesis out (M/D)
CLKFX180 => open, -- 180 degree CLK synthesis out
LOCKED => open, -- DCM LOCK status output
PSDONE => open, -- Dynamic phase adjust done output
STATUS => open, -- 8-bit DCM status bits output
CLKFB => iCLKFB_IN, -- DCM clock feedback
CLKIN => iCLKIN_IBUFG, -- Clock input (from IBUFG, BUFG or DCM)
PSCLK => '0', -- Dynamic phase adjust clock input
PSEN => '0', -- Dynamic phase adjust enable input
PSINCDEC => '0', -- Dynamic phase adjust increment/decrement
RST => '0' -- DCM asynchronous reset input
);
-- RAMB16_S9_S9: 2k x 8 + 1 Parity bit Dual-Port RAM
-- graphic data buffer
RAMB16_S9_S9_inst : RAMB16_S9_S9
generic map (
INIT_A => X"000", -- Value of output RAM registers on Port A at startup
INIT_B => X"000", -- Value of output RAM registers on Port B at startup
SRVAL_A => X"000", -- Port A ouput value upon SSR assertion
SRVAL_B => X"000", -- Port B ouput value upon SSR assertion
WRITE_MODE_A => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
WRITE_MODE_B => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL"
-- The following INIT_xx declarations specify the initial contents of the RAM
-- Address 0 to 511
INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 512 to 1023
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 1024 to 1535
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 1536 to 2047
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- The next set of INITP_xx are for the parity bits
-- Address 0 to 511
INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 512 to 1023
INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 1024 to 1535
INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 1536 to 2047
INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
port map (
DOA => open, -- Port A 8-bit Data Output
DOB => iDOB, -- Port B 8-bit Data Output
DOPA => open, -- Port A 1-bit Parity Output
DOPB => open, -- Port B 1-bit Parity Output
ADDRA => iCADRA, -- Port A 11-bit Address Input
ADDRB => iCADRB, -- Port B 11-bit Address Input
CLKA => iCLKFX_OUT,-- Port A Clock
CLKB => iCLKFX_OUT,-- Port B Clock
DIA => iDIA, -- Port A 8-bit Data Input
DIB => X"FF", -- Port B 8-bit Data Input
DIPA => "1", -- Port A 1-bit parity Input
DIPB => "1", -- Port-B 1-bit parity Input
ENA => '1', -- Port A RAM Enable Input
ENB => '0', -- Port B RAM Enable Input
SSRA => '0', -- Port A Synchronous Set/Reset Input
SSRB => '0', -- Port B Synchronous Set/Reset Input
WEA => iWEA, -- Port A Write Enable Input
WEB => '0' -- Port B Write Enable Input
);
-- RAMB16_S1_S1: 16k x 1 Dual-Port RAM
-- Spartan-3
-- Xilinx HDL Language Template, version 12.2
XBUFX : RAMB16_S1_S1
generic map (
INIT_A => "0", -- Value of output RAM registers on Port A at startup
INIT_B => "0", -- Value of output RAM registers on Port B at startup
SRVAL_A => "0", -- Port A ouput value upon SSR assertion
SRVAL_B => "0", -- Port B ouput value upon SSR assertion
WRITE_MODE_A => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
WRITE_MODE_B => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL"
-- The following INIT_xx declarations specify the initial contents of the RAM
-- Address 0 to 4095
INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 4096 to 8191
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 8192 to 12287
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 12288 to 16383
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000")
port map (
DOA => open, -- Port A 1-bit Data Output
DOB => iBDOB, -- Port B 1-bit Data Output
ADDRA => iBADRA, -- Port A 14-bit Address Input
ADDRB => iBADRB, -- Port B 14-bit Address Input
CLKA => iCLKFX_OUT, -- Port A Clock
CLKB => iCLKFX_OUT, -- Port B Clock
DIA => iBDIA, -- Port A 1-bit Data Input
DIB => "0", -- Port B 1-bit Data Input
ENA => '1', -- Port A RAM Enable Input
ENB => '0', -- PortB RAM Enable Input
SSRA => '0', -- Port A Synchronous Set/Reset Input
SSRB => '0', -- Port B Synchronous Set/Reset Input
WEA => iBWEA, -- Port A Write Enable Input
WEB => '0' -- Port B Write Enable Input
);
-- local clock input
-- 3rd March 2013 added
iPCLK <= PCLK ;
iHREF <= HREF ;
-- monitor output
GLED <= not ENPULSE ;
RLED <= iICLK ;
MVS <= not iVSTRG ;
HPCLK <= not iPCLK ;
STATEX <= not iCSTATEX ;
ATRGX <= not iWEA ;
BTRGX <= not iBTRG ;
WTRGX <= not iLTRG ;
-- camera data out
XMOUT <= iCDATA(15 downto 12) when ( XMOUTSEL = "11" ) else
iCDATA(11 downto 8) when ( XMOUTSEL = "10" ) else
iCDATA( 7 downto 4) when ( XMOUTSEL = "01" ) else
iCDATA( 3 downto 0) ;
-- trigger
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iTRG_SFT <= "000" ;
iCTRG_SFT <= "000" ;
elsif rising_edge(iCLKFX_OUT) then
iTRG_SFT <= iTRG_SFT(1 downto 0) & GP2(6) ;
iCTRG_SFT <= iCTRG_SFT(1 downto 0) & GP2(7) ;
end if ;
end process ;
iTRG <= '1' when ( iTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ;
iCTRG <= '1' when ( iCTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ;
-- BUS interface (latch)
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- register address
iDADR <= (others => '0') ;
-- register data
iDDAT <= (others => '0') ;
elsif rising_edge(iCLKFX_OUT) then
if ( GP2(5 downto 4) = "10" ) then
iDADR <= GP2(3 downto 0) ;
iDDAT <= GP3 ;
end if ;
end if ;
end process ;
-- BUS interface (write from external circuit)
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iDSTATE <= "00" ; -- state control
-- direction
iDIRF <= "00" ; -- forward
iDIRR <= "01" ; -- reverse
-- duty ratio
iDUTYF <= (others => '0') ;
iDUTYR <= (others => '0') ;
-- target line
iTLTOP <= (others => '0') ;
iTLMIDDLE <= (others => '0') ;
iTLBOTTOM <= (others => '0') ;
-- rotate pulse trigger
iSETPLS <= '0' ;
elsif falling_edge(iCLKFX_OUT) then
case conv_integer(iDSTATE) is
-- wait trigger
when 0 => if ( iTRG = '1' ) then
iDSTATE <= "01" ;
else
iDSTATE <= "00" ;
end if ;
-- deliver
when 1 => iDSTATE <= "11" ;
-- direction forword
if ( iDADR = "0000" ) then
iDIRF <= iDDAT(1 downto 0) ;
end if ;
-- forword duty
if ( iDADR = "0001" ) then
iDUTYF <= iDDAT(6 downto 0) ;
end if ;
-- direction reverse
if ( iDADR = "0010" ) then
iDIRR <= iDDAT(1 downto 0) ;
end if ;
-- reverse duty
if ( iDADR = "0011" ) then
iDUTYR <= iDDAT(6 downto 0) ;
end if ;
-- target line TOP
if ( iDADR = "1011" ) then
iTLTOP <= iDDAT ;
end if ;
-- target line MIDDLE
if ( iDADR = "1100" ) then
iTLMIDDLE <= iDDAT ;
end if ;
-- target line BOTTOM
if ( iDADR = "1101" ) then
iTLBOTTOM <= iDDAT ;
end if ;
-- clear distance pulse (upper)
if ( iDADR = "1110" ) then
iECNTX(15 downto 8) <= iDDAT ;
iSETPLS <= '1' ;
end if ;
-- clear distance pulse (lower)
if ( iDADR = "1111" ) then
iECNTX( 7 downto 0) <= iDDAT ;
iSETPLS <= '1' ;
end if ;
-- delay
when 3 => iDSTATE <= "10" ;
iSETPLS <= '0' ;
-- return first state
when 2 => iDSTATE <= "00" ;
-- default
when others =>
iDSTATE <= "00" ;
end case ;
end if ;
end process ;
-- motor control output
FOUT <= iFOUT ;
ROUT <= iROUT ;
-- BUS interface data
GP3 <= iDAT when ( GP2(5 downto 4) = "01" ) else (others => 'Z');
-- register file
-- front direction 0
-- front duty 1
-- rear direction 2
-- rear duty 3
-- TOP distance 4
-- MIDDLE distance 5
-- BOTTOM distance 6
-- camera data 7
-- TOP 8
-- MIDDLE 9
-- BOTTOM 10
-- target line TOP 11
-- target line MIDDLE 12
-- target line BOTTOM 13
-- encoder counter(high) 14
-- encoder counter(low) 15
iDAT <= "000000" & iDIRF when ( GP2(3 downto 0) = "0000" ) else -- front direction
'0' & iDUTYF when ( GP2(3 downto 0) = "0001" ) else -- front duty
"000000" & iDIRR when ( GP2(3 downto 0) = "0010" ) else -- rear direction
'0' & iDUTYR when ( GP2(3 downto 0) = "0011" ) else -- rear duty
iLTOPD when ( GP2(3 downto 0) = "0100" ) else -- TOP distance
iLMIDDLED when ( GP2(3 downto 0) = "0101" ) else -- MIDDLE distance
iLBOTTOMD when ( GP2(3 downto 0) = "0110" ) else -- BOTTOM distance
iDOB when ( GP2(3 downto 0) = "0111" ) else -- camera data
iLTOP when ( GP2(3 downto 0) = "1000" ) else -- TOP
iLMIDDLE when ( GP2(3 downto 0) = "1001" ) else -- MIDDLE
iLBOTTOM when ( GP2(3 downto 0) = "1010" ) else -- BOTTOM
iTLTOP when ( GP2(3 downto 0) = "1011" ) else -- target line TOP
iTLMIDDLE when ( GP2(3 downto 0) = "1100" ) else -- target line MIDDLE
iTLBOTTOM when ( GP2(3 downto 0) = "1101" ) else -- target line BOTTOM
iECNT(15 downto 8) when ( GP2(3 downto 0) = "1110" ) else -- encoder counter(high)
iECNT( 7 downto 0) when ( GP2(3 downto 0) = "1111" ) else -- encoder counter(low)
X"FF" ; -- dummy
-- VSYNC synchronizer
-- 3rd March 2013 update iSCLK -> iPCLK
-- 14th March 2013 iPCLK -> iCLKFX_OUT
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iVS_SFT <= "000" ;
iHREF_SFT <= "000" ;
elsif rising_edge(iCLKFX_OUT) then
iVS_SFT <= iVS_SFT(1 downto 0) & VS ;
iHREF_SFT <= iHREF_SFT(1 downto 0) & iHREF ;
end if ;
end process ;
iVSTRG <= '1' when ( iVS_SFT = "011" or iVS_SFT = "001" ) else '0' ;
iHREF_TRG <= '1' when ( iHREF_SFT = "011" or iHREF_SFT = "001" ) else '0' ;
-- store camera data
process (nRESET,iPCLK)
begin
if ( nRESET = '0' ) then
iCDATA <= (others => '0') ;
iPCNT <= (others => '0') ;
elsif rising_edge(iPCLK) then
-- store data
if ( iHREF = '1' ) then
iCDATA <= iCDATA(7 downto 0) & CDAT ;
iPCNT <= iPCNT + 1 ;
end if ;
-- judge
if ( conv_integer(iPCNT) = PCNT_MAX2 ) then
iPCNT <= (others => '0') ;
end if ;
end if ;
end process ;
-- update pixel counter
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
iPCNTX <= (others => '0') ;
elsif rising_edge(iCLKFX_OUT) then
-- shift
iPCNTX <= iPCNTX(8 downto 0) & iPCNT ;
end if ;
end process ;
-- previous != current and current LSB = 0
iPCNT_TRG <= '1' when ( iPCNTX(17 downto 9) /= iPCNTX(8 downto 0) and iPCNT(0) = '0' ) else '0' ;
-- store graphic data to Dual Port Memory
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iASTATE <= 0 ;
-- dual port memory address
iCADRA <= (others => '0') ;
-- maximum
iTMAX <= (others => '0') ;
iMMAX <= (others => '0') ;
iBMAX <= (others => '0') ;
-- minimum
iTMIN <= (others => '1') ;
iMMIN <= (others => '1') ;
iBMIN <= (others => '1') ;
-- threshold
iTHVT <= 128 ;
iTHVM <= 128 ;
iTHVB <= 128 ;
elsif rising_edge(iCLKFX_OUT) then
case iASTATE is
-- wait store trigger
when 0 => if ( iPCNT_TRG = '1' ) then
iASTATE <= 1 ; -- next
else
iASTATE <= 0 ; -- stay
end if ;
-- get Y signal data
when 1 => iASTATE <= 2 ; -- next
iCYDAT <= iCDATA(15 downto 8) ;
-- judge store or skip
when 2 => if ( iTARGET_LA = '1' ) then
iASTATE <= 3 ; -- store
else
iASTATE <= 6 ; -- skip
end if ;
-- copy Y signal
when 3 => iASTATE <= 4 ; -- next
iDIA <= iCYDAT ;
-- store Y signal to dual port memory
-- update maximum and mininum
when 4 => iASTATE <= 5 ; -- next
-- TOP
if ( iTARGET_LT = '1' ) then
-- maximum
if ( conv_integer(iTMAX) < conv_integer(iCYDAT) ) then
iTMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iTMIN) > conv_integer(iCYDAT) ) then
iTMIN <= iCYDAT ;
end if ;
end if ;
-- MIDDLE
if ( iTARGET_LM = '1' ) then
-- maximum
if ( conv_integer(iMMAX) < conv_integer(iCYDAT) ) then
iMMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iMMIN) > conv_integer(iCYDAT) ) then
iMMIN <= iCYDAT ;
end if ;
end if ;
-- BOTTOM
if ( iTARGET_LB = '1' ) then
-- maximum
if ( conv_integer(iBMAX) < conv_integer(iCYDAT) ) then
iBMAX <= iCYDAT ;
end if ;
-- minimum
if ( conv_integer(iBMIN) > conv_integer(iCYDAT) ) then
iBMIN <= iCYDAT ;
end if ;
end if ;
-- address increment (dual port memory)
when 5 => iASTATE <= 6 ; -- next
if ( iTARGET_LTMB = '1' ) then
iCADRA <= iCADRA + 1 ;
end if ;
-- judge
when 6 => if ( iCADRA = QMAX ) then
iASTATE <= 7 ; -- exit loop
else
iASTATE <= 0 ; -- loop
end if ;
-- calculate
when 7 => iASTATE <= 8 ; -- next
-- threshold
iTHVT <= (conv_integer(iTMAX) + conv_integer(iTMIN)) / 2 ;
iTHVM <= (conv_integer(iMMAX) + conv_integer(iMMIN)) / 2 ;
iTHVB <= (conv_integer(iBMAX) + conv_integer(iBMIN)) / 2 ;
-- prepare next stage
when 8 => iASTATE <= 9 ; -- next
-- dual port memory address
iCADRA <= (others => '0') ;
-- maximum
iTMAX <= (others => '0') ;
iMMAX <= (others => '0') ;
iBMAX <= (others => '0') ;
-- minimum
iTMIN <= (others => '1') ;
iMMIN <= (others => '1') ;
iBMIN <= (others => '1') ;
-- return first state
when 9 => iASTATE <= 0 ;
-- default
when others =>
iASTATE <= 0 ;
end case ;
end if ;
end process ;
-- store Y data to camera buffer (trigger)
iWEA <= '1' when ( iASTATE = 4 ) else '0' ;
-- camera sequencer
-- 000 wait CTRG
-- 001 wait VTRG
-- 011 wait HFEF edge
-- 111 line counter increment
-- 110 judge last line counter
-- 100 return first state
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iCSTATE <= "000" ;
-- line counter
iLCNT <= 0 ;
elsif rising_edge(iCLKFX_OUT) then
case conv_integer(iCSTATE) is
-- wait trigger from micro computer
when 0 => if ( iCTRG = '1' ) then
iCSTATE <= "001" ; -- next
else
iCSTATE <= "000" ; -- stay
end if ;
-- wait VSYNC trigger
when 1 => if ( iVSTRG = '1' ) then
iCSTATE <= "011" ; -- next
else
iCSTATE <= "001" ; -- stay
end if ;
-- wait HREF_TRG
when 3 => if ( iHREF_TRG = '1' ) then
iCSTATE <= "111" ; -- next
else
iCSTATE <= "011" ; -- stay
end if ;
-- line counter increment
when 7 => iCSTATE <= "110" ; -- next
iLCNT <= iLCNT + 1 ;
-- judge line counter is last value
when 6 => if ( iLCNT = LCNT_MAX ) then
iCSTATE <= "100" ; -- exit loop
else
iCSTATE <= "011" ; -- loop
end if ;
-- return first state
when 4 => iCSTATE <= "000" ;
-- clear line counter
iLCNT <= 0 ;
-- default
when others =>
iCSTATE <= "000" ;
end case ;
end if ;
end process ;
-- binary conversion (trigger)
iBTRG <= '1' when ( iCSTATE = "100" ) else '0' ;
-- monitor
iCSTATEX <= iSTORE_FLAG & iCSTATE ;
-- binary conversion (trigger)
-- 000 wait CTRG : disable
-- 001 wait VTRG : enable
-- 011 wait HFEF edge : enable
-- 111 line counter increment : enable
-- 110 judge last line counter : enable
-- 100 return first state : disable
iSTORE_FLAG <= iCSTATE(1) or iCSTATE(0) ;
-- target line flag
iTARGET_LTMB <= iTARGET_LT or iTARGET_LM or iTARGET_LB ;
iTARGET_LA <= iTARGET_LTMB and iSTORE_FLAG ;
iTARGET_LT <= '1' when ( iLCNT = conv_integer(iTLTOP) ) else '0' ;
iTARGET_LM <= '1' when ( iLCNT = conv_integer(iTLMIDDLE) ) else '0' ;
iTARGET_LB <= '1' when ( iLCNT = conv_integer(iTLBOTTOM) ) else '0' ;
-- B port sequencer (store binary code)
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iBSTATE <= 0 ;
-- address
iCADRB <= (others => '0') ; -- camera buffer
iBADRA <= (others => '0') ; -- binary code buffer
-- data
iBDAT <= (others => '0') ; -- camera buffer data
iBDIA <= (others => '0') ; -- binary code
-- measure flag
iBFLAG <= 0 ;
elsif rising_edge(iCLKFX_OUT) then
case conv_integer(iBSTATE) is
-- wait trigger
when 0 => if ( iBTRG = '1' ) then
iBSTATE <= 1 ; -- next
-- initialize address
iCADRB <= (others => '0') ; -- camera buffer
iBADRA <= (others => '0') ; -- binary code
else
iBSTATE <= 0 ; -- stay
end if ;
-- initialize
when 1 => iBSTATE <= 2 ; -- next
iBCNT <= 0 ;
-- get data from camera buffer
when 2 => iBSTATE <= 3 ; -- next
iBDAT <= iDOB ;
iBCNT <= iBCNT + 1 ; -- increment counter
-- camera buffer address increment
when 3 => iBSTATE <= 4 ; -- next
iCADRB <= iCADRB + 1 ;
iBDIA <= "0" ;
-- compare
when 4 => iBSTATE <= 5 ; -- next
-- TOP
if ( iBFLAG = 0 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVT) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- MIDDLE
if ( iBFLAG = 1 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVM) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- BOTTOM
if ( iBFLAG = 2 ) then
if ( conv_integer(iBDAT) > conv_integer(iTHVB) ) then
iBDIA <= "1" ;
else
iBDIA <= "0" ;
end if ;
end if ;
-- store
when 5 => iBSTATE <= 6 ; -- next
-- binary data address increment
when 6 => iBSTATE <= 7 ; -- next
iBADRA <= iBADRA + '1' ;
-- judge
when 7 => if ( iBCNT = PCNT_MAX ) then
iBSTATE <= 8 ; -- next
else
iBSTATE <= 2 ; -- loop
end if ;
-- flag increment
when 8 => iBSTATE <= 9 ; -- next
iBFLAG <= iBFLAG + 1 ; -- update
iBCNT <= 0 ;
-- judge
when 9 => if ( iBFLAG = 3 ) then
iBSTATE <= 10 ; -- exit
else
iBSTATE <= 1 ; -- loop
end if ;
-- complete and send trigger
when 10 => iBSTATE <= 11 ; -- next
iBFLAG <= 0 ; -- clear flag
-- return first state
when 11 => iBSTATE <= 0 ; -- first state
-- default
when others =>
iBSTATE <= 0 ;
end case ;
end if ;
end process ;
-- binary data store trigger
iBWEA <= '1' when ( iBSTATE = 5 ) else '0' ;
-- generate parameters trigger
iLTRG <= '1' when ( iBSTATE = 10 ) else '0' ;
-- last sequencer
process (nRESET,iCLKFX_OUT)
begin
if ( nRESET = '0' ) then
-- state
iLSTATE <= 0 ;
-- address
iBADRB <= (others => '0') ;
-- data
iWNOW <= 0 ;
iWNEXT <= 0 ;
-- result
iLTOP <= (others => '1') ;
iLMIDDLE <= (others => '1') ;
iLBOTTOM <= (others => '1') ;
iLTOPD <= (others => '1') ;
iLMIDDLED <= (others => '1') ;
iLBOTTOMD <= (others => '1') ;
-- counter
iWCNT <= 0 ;
-- Zero -> Plus
iWZP <= 255 ;
-- Plus -> Zero
iWPZ <= 255 ;
elsif rising_edge(iCLKFX_OUT) then
case conv_integer(iLSTATE) is
-- wait trigger
when 0 => if ( iLTRG = '1' ) then
iLSTATE <= 1 ; -- next
-- address
iBADRB <= (others => '0') ;
-- flag
iWFLAG <= 0 ;
else
iLSTATE <= 0 ; -- stay
end if ;
-- initialize (get first data)
when 1 => iLSTATE <= 2 ; -- next
iWNOW <= conv_integer(iBDOB) ;
-- counter
iWCNT <= 0 ;
-- Zero -> Plus
iWZP <= 255 ;
-- Plus -> Zero
iWPZ <= 255 ;
-- address increment
when 2 => iLSTATE <= 3 ;
iBADRB <= iBADRB + '1' ;
iWCNT <= iWCNT + 1 ;
-- get next data
when 3 => iLSTATE <= 4 ; -- next
iWNEXT <= conv_integer(iBDOB) ;
-- judge edge
when 4 => iLSTATE <= 5 ;
-- zero => positive
if ( iWNOW = 0 and iWNEXT = 1 ) then
iWZP <= iWCNT ;
end if ;
-- positive => zero
if ( iWNOW = 1 and iWNEXT = 0 ) then
iWPZ <= iWCNT ;
end if ;
-- judge counter
when 5 => if ( iWCNT = PCNT_MAX ) then
iLSTATE <= 6 ; -- exit loop
else
iLSTATE <= 2 ; -- loop
-- shift
iWNOW <= iWNEXT ;
end if ;
-- calculate
when 6 => iLSTATE <= 7 ;
-- top
if ( iWFLAG = 0 ) then
-- all WHITE or all BLACK
if ( iWZP = 255 and iWPZ = 255 ) then
-- distance
iLTOPD <= (others => '0') ;
-- location
if ( iWNOW = 1 ) then -- white
iLTOP <= conv_std_logic_vector(PCNT_MAX,8) ;
else -- black
iLTOP <= (others => '0') ;
end if ;
end if ;
-- left WHITE
if ( iWZP = 255 and iWPZ < PCNT_MAX ) then
-- location
iLTOP <= (others => '0') ;
-- distance
iLTOPD <= conv_std_logic_vector(iWPZ,8) ;
end if ;
-- right WHITE
if ( iWZP < PCNT_MAX and iWPZ = 255 ) then
-- location
iLTOP <= conv_std_logic_vector(PCNT_MAX,8) ;
-- distance
iLTOPD <= conv_std_logic_vector(iWZP,8) ;
end if ;
-- others
if ( iWZP < PCNT_MAX and iWPZ < PCNT_MAX ) then
-- location
iLTOP <= conv_std_logic_vector((iWZP + iWPZ) / 2,8) ;
-- distance
if ( iWZP < iWPZ ) then
iLTOPD <= conv_std_logic_vector(iWPZ - iWZP,8) ;
else
iLTOPD <= conv_std_logic_vector(iWZP - iWPZ,8) ;
end if ;
end if ;
end if ;
-- middle
if ( iWFLAG = 1 ) then
-- all WHITE or all BLACK
if ( iWZP = 255 and iWPZ = 255 ) then
-- distance
iLMIDDLED <= (others => '0') ;
-- location
if ( iWNOW = 1 ) then -- white
iLMIDDLE <= conv_std_logic_vector(PCNT_MAX,8) ;
else -- black
iLMIDDLE <= (others => '0') ;
end if ;
end if ;
-- left WHITE
if ( iWZP = 255 and iWPZ < PCNT_MAX ) then
-- location
iLMIDDLE <= (others => '0') ;
-- distance
iLMIDDLED <= conv_std_logic_vector(iWPZ,8) ;
end if ;
-- right WHITE
if ( iWZP < PCNT_MAX and iWPZ = 255 ) then
-- location
iLMIDDLE <= conv_std_logic_vector(PCNT_MAX,8) ;
-- distance
iLMIDDLED <= conv_std_logic_vector(iWZP,8) ;
end if ;
-- others
if ( iWZP < PCNT_MAX and iWPZ < PCNT_MAX ) then
-- location
iLMIDDLE <= conv_std_logic_vector((iWZP + iWPZ) / 2,8) ;
-- distance
if ( iWZP < iWPZ ) then
iLMIDDLED <= conv_std_logic_vector(iWPZ - iWZP,8) ;
else
iLMIDDLED <= conv_std_logic_vector(iWZP - iWPZ,8) ;
end if ;
end if ;
end if ;
-- bottom
if ( iWFLAG = 2 ) then
-- all WHITE or all BLACK
if ( iWZP = 255 and iWPZ = 255 ) then
-- distance
iLBOTTOMD <= (others => '0') ;
-- location
if ( iWNOW = 1 ) then -- white
iLBOTTOM <= conv_std_logic_vector(PCNT_MAX,8) ;
else -- black
iLBOTTOM <= (others => '0') ;
end if ;
end if ;
-- left WHITE
if ( iWZP = 255 and iWPZ < PCNT_MAX ) then
-- location
iLBOTTOM <= (others => '0') ;
-- distance
iLBOTTOMD <= conv_std_logic_vector(iWPZ,8) ;
end if ;
-- right WHITE
if ( iWZP < PCNT_MAX and iWPZ = 255 ) then
-- location
iLBOTTOM <= conv_std_logic_vector(PCNT_MAX,8) ;
-- distance
iLBOTTOMD <= conv_std_logic_vector(iWZP,8) ;
end if ;
-- others
if ( iWZP < PCNT_MAX and iWPZ < PCNT_MAX ) then
-- location
iLBOTTOM <= conv_std_logic_vector((iWZP + iWPZ) / 2,8) ;
-- distance
if ( iWZP < iWPZ ) then
iLBOTTOMD <= conv_std_logic_vector(iWPZ - iWZP,8) ;
else
iLBOTTOMD <= conv_std_logic_vector(iWZP - iWPZ,8) ;
end if ;
end if ;
end if ;
-- update flag
when 7 => iLSTATE <= 8 ;
iWFLAG <= iWFLAG + 1 ;
-- address
-- judge flag
when 8 => if ( iWFLAG = 3 ) then
iLSTATE <= 9 ; -- exit loop
else
iLSTATE <= 1 ; -- loop
end if ;
-- return first state
when 9 => iLSTATE <= 0 ;
-- default
when others =>
iLSTATE <= 0 ;
end case ;
end if ;
end process ;
-- encoder counter
process (nRESET,iSCLK)
begin
if ( nRESET = '0' ) then
iENPLS_SFT <= "000" ;
elsif rising_edge(iSCLK) then
iENPLS_SFT <= iENPLS_SFT(1 downto 0) & ENPULSE ;
end if ;
end process ;
iENPLS <= '1' when ( iENPLS_SFT = "011" ) else '0' ;
process (nRESET,iSETPLS,iSCLK,iECNTX)
begin
if ( nRESET = '0' ) then
iECNT <= (others => '0') ;
elsif ( iSETPLS = '1' ) then
iECNT <= iECNTX ;
elsif rising_edge(iSCLK) then
if ( iENPLS = '1' ) then
iECNT <= iECNT + '1' ;
end if ;
end if ;
end process ;
end Behavioral;
画像処理関係ブロック図
水平、垂直のためのカウンタ処理は、PCLK、VSYNC、
HREFから生成します。また、水平方向のカウンタの
処理に同期して、画像データを取得します。
画像データをメモリに保存するタイミングは、マイコン
から与えられるトリガーで生成します。
画像データを2値化して、別のメモリに保存します。
動作開始は、画像データを保存するシーケンサから
与えます。
2値化データをスキャンして、センターラインの幅
センターライン中央位置を算出します。
目次
前
次