目次

VHDLコード改造

 日常生活に復帰してから、VHDLコードを見直しました。
 改造すべき内容は、次の3項目です。

 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値化データをスキャンして、センターラインの幅  センターライン中央位置を算出します。
目次

inserted by FC2 system