目次

PLDによるハードテスト

 Z80ボードは、ROMの中にプログラムを焼きこむ時間が必要に
 なり、効率が悪いとわかりました。

 もう少し、単純かつ短時間でテストするために、PLD
 (Programmable Logic Device)を使うことにします。

 手元には複数のCPLD/FPGAボードがあるので、そのうち
 現在出番の少なくなったXilinxの3.3V動作CPLDボードを
 使います。



 このボードには、XC9572XLとCoolRunnerIIが載っているので
 それぞれに、以下の電子回路のテストをさせます。


 ボードには、フリースペースがありますが、再利用したい
 ので、中継コネクタ+コネクタ基板を作成しました。



 40ピンコネクタから、10ピンコネクタx4に変換し
 10ピンケーブルで、MCR-VCマシンを構成する基板に
 接続できるようにします。




 40ピンコネクタのピン配置は、以下です。

   1 GND        2 VU
   3 Vdd(3.3V)  4 P44 <LED>
   5 P43        6 P42
   7 P41        8 P40
   9 P39       10 P38
  11 P37       12 P36
  13 P34       14 P33 <RESET>
  15 P32       16 P31
  17 P30       18 P29
  19 P28       20 P27
  21 P23       22 P22
  23 P21       24 P20
  25 P19       26 P7
  27 ---       28 ---
  29 ---       30 P3
  31 P2        32 P1  <CLOCK>
  33 P18       34 P16
  35 P14       36 P13
  37 P12       38 P8
  39 P6        40 P5


 40ピンコネクタを挿し込むと、次のようになります。



 利用できるピンは全部で33ピンですが、一部は、リセット、
 クロック、テスト用LEDに使われているので、10ピンコネクタを
 A〜Dの4グループに分けて、接続を決めます。

  GroupA
     1 Vdd
     2 P43
     3 P42
     4 P41
     5 P40
     6 P39
     7 P38
     8 P37
     9 P36
    10 GND

  GroupB
     1 Vdd
     2 P34
     3 P32
     4 P31
     5 P30
     6 P29
     7 P28
     8 P27
     9 P23
    10 GND

  GroupC
     1 Vdd
     2 ---
     3 P22
     4 P21
     5 P20
     6 P19
     7 P7
     8 P3
     9 P2
    10 GND

  GroupD
     1 Vdd
     2 P18
     3 P16
     4 P14
     5 P13
     6 P12
     7 P8
     8 P6
     9 P5
    10 GND


 密着センサーの動作テストを考えてみると、センサーから
 データを入力し、LEDに表示することにします。






 8ビットデータを、トリガークリックで、LEDに表示します。
 VHDLコードで記述します。


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mcrvc1 is
  Generic ( 
    BSIZE  : integer := 8 ;
    CSIZE  : integer := 3 ;
    BOTTOM : integer := 0 -- ;
  );
  Port (
    -- system 
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- input 
    SENSOR : in  std_logic_vector(BSIZE-1 downto BOTTOM) ;
    -- trigger 
    TRG    : in  std_logic ;
    -- output
    LED    : out std_logic ;
    LEDOUT : out std_logic_vector(BSIZE-1 downto BOTTOM)-- ;
  );
end mcrvc1;

architecture behavioral of mcrvc1 is
  signal iREG  : std_logic_vector(BSIZE-1 downto BOTTOM) ;
  signal iSTRG : std_logic_vector(CSIZE-1 downto BOTTOM) ;
  signal iTRG  : std_logic ;
begin
  -- output
  LEDOUT <= iREG ;
  LED    <= not iTRG ;

  -- input
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSTRG <= "000" ;
    elsif rising_edge( CLOCK ) then
      iSTRG <= iSTRG(1 downto 0) & TRG ;
    end if ;
  end process ;
  iTRG <= '1' when ( iSTRG = "011" or iSTRG = "001" ) else '0' ;

  -- latch
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iREG <= (others => '0') ;
    elsif rising_edge( CLOCK ) then
      if ( iTRG = '1' ) then
        iREG <= not SENSOR ;
      end if ;
    end if ;
  end process ;

end behavioral;

 ピン配置を定義します。

#  system
NET "LED"    LOC = "P44" ;
NET "nRESET" LOC = "P33" ;
NET "CLOCK"  LOC = "P1" ;

#  group A
NET "SENSOR<7>" LOC = "P43" ;
NET "SENSOR<6>" LOC = "P42" ;
NET "SENSOR<5>" LOC = "P41" ;
NET "SENSOR<4>" LOC = "P40" ;
NET "SENSOR<3>" LOC = "P39" ;
NET "SENSOR<2>" LOC = "P38" ;
NET "SENSOR<1>" LOC = "P37" ;
NET "SENSOR<0>" LOC = "P36" ;

#  group B
NET "LEDOUT<7>" LOC = "P34" ;
NET "LEDOUT<6>" LOC = "P32" ;
NET "LEDOUT<5>" LOC = "P31" ;
NET "LEDOUT<4>" LOC = "P30" ;
NET "LEDOUT<3>" LOC = "P29" ;
NET "LEDOUT<2>" LOC = "P28" ;
NET "LEDOUT<1>" LOC = "P27" ;
NET "LEDOUT<0>" LOC = "P23" ;

#  group C(7bits)
NET "TRG"       LOC = "P22" ;

 次にモータ制御ボードのテストをします。



 写真の右側に見えるMOS-FET、ドライバには2つの
 LEDを接続してあり、PWM波形が入ると、LEDが点灯
 する仕掛けがあります。

 左側には、赤8本、緑8本のLEDを実装しています。
 赤LEDは、密着型センサーのモニタ用です。緑LEDは
 内部状態を表示するインディケータにしてあります。
 中央に、LEDとスイッチを配置しています。モード指定

 とスタートトリガーを、トグルとプッシュスイッチに
 割当てています。緑LEDで表示できない、緊急状態に
 システムが陥ったときや、センターラインと交差する
 白線を検出したことを示すLEDを用意しています。


 赤LED、緑LEDの点灯表示テスト、中央2個のスイッチの
 ON/OFFを2個のLEDでモニタします。
 モータドライバへの出力は、カウンタを用意して、カウンタ
 の出力を接続します。


 3つの内容を含めたVHDLコードは、以下としました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mcrvc7 is
  generic (
    PMAX   : integer := 40000 ;
    TOP    : integer := 22 ;
    BSIZE  : integer :=  2 ;
    CSIZE  : integer :=  8 ;
    BOTTOM : integer :=  0 --;
  ) ;
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- input
    SWX    : in  std_logic_vector(BSIZE-1 downto BOTTOM) ;
    -- output
    LED    : out std_logic ;
    LOUT   : out std_logic_vector(BSIZE-1 downto BOTTOM) ;
    RLOUT  : out std_logic_vector(CSIZE-1 downto BOTTOM) ; -- red   LED
    GLOUT  : out std_logic_vector(CSIZE-1 downto BOTTOM) ; -- green LED
    PWMX   : out std_logic_vector(BSIZE-1 downto BOTTOM) --;
  ) ;
end mcrvc7;

architecture Behavioral of mcrvc7 is
  signal iSCNT  : std_logic_vector(TOP-1 downto BOTTOM)   ;
  signal iLCNT  : std_logic_vector(BSIZE   downto BOTTOM) ;
  signal iPWMX  : std_logic_vector(BSIZE-1 downto BOTTOM) ;
  signal iSWX   : std_logic_vector(BSIZE-1 downto BOTTOM) ;
  signal iGLOUT : std_logic_vector(CSIZE-1 downto BOTTOM) ;
begin
  -- output
  LOUT  <= not iSWX   ;
  RLOUT <= not iGLOUT ;
  GLOUT <= not iGLOUT ;
  PWMX  <= iPWMX  ; 
  LED   <= not iSCNT(TOP-1) ;

  -- divider
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSCNT <= (others => '0') ;
    elsif rising_edge( CLOCK ) then
      -- increment
      iSCNT <= iSCNT + '1' ;
    end if ;
  end process ;

  -- local counter
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iLCNT <= "000" ;
      iPWMX <= "00" ;
    elsif rising_edge( CLOCK ) then
      -- increment
      iLCNT <= iSCNT(TOP-4 downto TOP-6) ;
      iPWMX <= iSCNT(TOP-4 downto TOP-5) ;
    end if ;
  end process ;

  -- latch
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSWX <= "00" ;
    elsif falling_edge( CLOCK ) then
      if ( iSCNT(TOP-8 downto TOP-9) = "11" ) then 
        iSWX <= not SWX ;
      end if ;
    end if ;
  end process ;
  
  -- decoder
  iGLOUT <= "00000001" when ( iLCNT = "000" ) else 
            "00000010" when ( iLCNT = "001" ) else
            "00000100" when ( iLCNT = "010" ) else
            "00001000" when ( iLCNT = "011" ) else
            "00010000" when ( iLCNT = "100" ) else
            "00100000" when ( iLCNT = "101" ) else
            "01000000" when ( iLCNT = "110" ) else
            "10000000" when ( iLCNT = "111" ) else
            "00000000" ;

end Behavioral;


 ピン配置は、次のように定義しました。

#  system
NET "LED"    LOC = "P44" ;
NET "nRESET" LOC = "P33" ;
NET "CLOCK"  LOC = "P1" ;

#  group A
NET "RLOUT<7>" LOC = "P43" ;
NET "RLOUT<6>" LOC = "P42" ;
NET "RLOUT<5>" LOC = "P41" ;
NET "RLOUT<4>" LOC = "P40" ;
NET "RLOUT<3>" LOC = "P39" ;
NET "RLOUT<2>" LOC = "P38" ;
NET "RLOUT<1>" LOC = "P37" ;
NET "RLOUT<0>" LOC = "P36" ;

#  group B
NET "PWMX<0>" LOC = "P34" ;
NET "PWMX<1>"  LOC = "P31" ;
NET "SWX<0>" LOC = "P29" ;
NET "SWX<1>" LOC = "P28" ;
NET "LOUT<1>" LOC = "P27" ;
NET "LOUT<0>" LOC = "P23" ;

#  group D
NET "GLOUT<7>" LOC = "P18" ;
NET "GLOUT<6>" LOC = "P16" ;
NET "GLOUT<5>" LOC = "P14" ;
NET "GLOUT<4>" LOC = "P13" ;
NET "GLOUT<3>" LOC = "P12" ;
NET "GLOUT<2>" LOC = "P8" ;
NET "GLOUT<1>" LOC = "P6" ;
NET "GLOUT<0>" LOC = "P5" ;

 赤LED8個、緑LED8個の接続をテストしている画像です。



 2つのスイッチの状態を、2つのLEDにモニタしています。



 モータドライバに、PWM波形が来ているかのテストです。




 制御ボードは、ピンでマイコンやCPLD/FPGAに接続する仕様
 なので、マイコン、FPGA、CPLDの種別を気にしないでテスト
 できます。

 ロータリーエンコーダから出力されてくるパルスを表示する
 処理を考えました。



 ロータリーエンコーダの出力を、シフトレジスタでとらえて
 立上りエッジがあった場合、内部カウンタに+1する仕様で
 コードを記述しました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mcrx4 is
  generic (
    TOPX : integer := 10 ; 
    RMAX : integer := 921 --;
  ) ;
  Port (
    -- system 
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- input 
    RCONR  : in  std_logic ; -- right clock trigger
    RCONL  : in  std_logic ; -- left  clock trigger
    -- OUTPUT 
    RCNT   : out std_logic_vector(7 downto 0) ;
    LCNT   : out std_logic_vector(7 downto 0) ;
    LED    : out std_logic --;
  );
end mcrx4;

architecture behavioral of mcrx4 is
  -- 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 ;
  -- LED handler
  component loutx is
    port(
      -- input
      CNTR   : in  std_logic_vector(7 downto 0) ;
      CNTL   : in  std_logic_vector(7 downto 0) ;
      -- output
      OCNTR  : out std_logic_vector(7 downto 0) ;
      OCNTL  : out std_logic_vector(7 downto 0) --;
    );
  end component ;
  -- clock
  signal iMCLK  : std_logic ;
  -- trigger
  signal iRCONR_SFT : std_logic_vector(2 downto 0) ;
  signal iRCONL_SFT : std_logic_vector(2 downto 0) ;
  signal iRCONR_TRG : std_logic ;
  signal iRCONL_TRG : std_logic ;
  -- internal counter
  signal iCNTRX : std_logic_vector(7 downto 0) ;
  signal iCNTLX : std_logic_vector(7 downto 0) ;
  -- output
  signal iROUTCNT : std_logic_vector(7 downto 0) ;
  signal iLOUTCNT : std_logic_vector(7 downto 0) ;
  -- update counter
  signal iCNTR : std_logic_vector(7 downto 0) ;
  signal iCNTL : std_logic_vector(7 downto 0) ;
  signal iUCNT : integer range 0 to 10 ;
begin
  -- clock
  CLKX : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iMCLK) ;

  -- LED handler
  LOUTXX : loutx port map (iCNTR,iCNTL,iROUTCNT,iLOUTCNT) ;

  -- output data
  RCNT <= iROUTCNT ;
  LCNT <= iLOUTCNT ;

  -- monitor
  LED   <= not iMCLK ;

  -- trigger handler
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iRCONR_SFT <= "000" ;
      iRCONL_SFT <= "000" ;
    elsif rising_edge(iMCLK) then
      iRCONR_SFT <= iRCONR_SFT(1 downto 0) & RCONR ;
      iRCONL_SFT <= iRCONL_SFT(1 downto 0) & RCONL ;
    end if ;
  end process ;
  iRCONR_TRG <= '1' when ( iRCONR_SFT = "011" or iRCONR_SFT = "001" ) else '0' ;
  iRCONL_TRG <= '1' when ( iRCONL_SFT = "011" or iRCONL_SFT = "001" ) else '0' ;

  -- counter
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iCNTRX <= (others => '0') ;
      iCNTLX <= (others => '0') ;
    elsif rising_edge(iMCLK) then
      if ( iRCONR_TRG = '1' ) then
        iCNTRX <= iCNTRX + '1' ;
      end if ;
      if ( iRCONL_TRG = '1' ) then
        iCNTLX <= iCNTLX + '1' ;
      end if ;
      if ( iUCNT = 10 ) then
        iCNTRX <= (others => '0') ;
        iCNTLX <= (others => '0') ;
      end if ;
    end if ;
  end process ;

  -- update
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iUCNT <= 0 ;
      iCNTR <= (others => '0') ;
      iCNTL <= (others => '0') ;
    elsif rising_edge(iMCLK) then
      if ( iUCNT = 10 ) then
        iUCNT <= 0 ;
        iCNTR <= iCNTRX ;
        iCNTL <= iCNTLX ;
      else
        iUCNT <= iUCNT + 1;
      end if ;
    end if ;
  end process ;

end behavioral;

 制御ボードには、赤と緑のLEDがあるので、カウント値を
 2進数で表示します。そのために、VHDLコードを定義して
 使います。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity loutx is
  port(
    -- input
    CNTR   : in  std_logic_vector(7 downto 0) ;
    CNTL   : in  std_logic_vector(7 downto 0) ;
    -- output
    OCNTR  : out std_logic_vector(7 downto 0) ;
    OCNTL  : out std_logic_vector(7 downto 0) --;
  );
end loutx;

architecture Behavioral of loutx is
  signal iOCNTR : std_logic_vector(7 downto 0);
  signal iOCNTL : std_logic_vector(7 downto 0);
begin
  -- input
  iOCNTR <= CNTR ;
  iOCNTL <= CNTL ;

  -- output
  OCNTR <= not iOCNTR ;
  OCNTL <= not iOCNTL ;

end Behavioral;

 クロックを分周するために、もうひとつVHDLコードを定義
 しました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity clkgenx is
  generic (
    TOPX : integer ; 
    RMAX : integer --;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- output
    CLKOUT : out std_logic -- ;
  );
end clkgenx;

architecture Behavioral of clkgenx is
  signal iSCNT : std_logic_vector(TOPX-1 downto 0);
  signal iCLK  : std_logic ;
begin
  -- output
  CLKOUT <= iCLK ;

  -- divider
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSCNT <= (others => '0') ;
      iCLK  <= '0' ;
    elsif rising_edge(CLOCK) then
      if ( conv_integer(iSCNT) = RMAX ) then
        iSCNT <= (others => '0') ;
        iCLK  <= not iCLK ;
      else
        iSCNT <= iSCNT + '1' ;
      end if ;
    end if ;
  end process ;

end Behavioral;


目次

inserted by FC2 system