目次

アナログマルチプレクサテスト

 CMOSの4051は、アナログマルチプレクサとして有名です。

 パラレルデータをシーケンシャルデータに変換して
 4ビットで、8ビットのデータを転送する用途での
 利用を考えました。

 半田付けした4051の基板は、以下。



 回路図は、次のように単純です。



 この基板をアダプタとして、路面センサーの8ビット
 データをピン数の少ないワンチップマイコンで扱える
 ようにしました。

 基板の動作テストに、CPLDのXC9572を利用。

 8ビットのDIPスイッチの情報を取得し、LEDアレイに
 反映させることで、動作をチェックします。

 テストは次のブロックで考えてみました。



 CPLDは、外部トリガーを与えられると4051を動かして
 シーケンシャルにデータを取得し、LEDに反映させます。

 シーケンシャル処理をしたいので、トリガーを与えられたなら
 一気に8ビットデータを取得することを考えました。



 必要なブロックを定義していきます。

 シンクロナイザ

  シンクロナイザで、外部から与えられるトリガーを検出して
  シーケンサが動くキッカケを生成。

  シフトレジスタを利用して、立ち上がりエッジを捉えます。

  VHDLコードにすると、以下。

      process (nRESET,CLOCK)
      begin
        if ( nRESET = '0' ) then
          iSFT <= "000" ;
        elsif rising_edge(CLOCK) then
          iSFT <= iSFT(1 downto 0) & XGTRG ;
        end if ;
      end process ;
      iTRG <= '1' when ( iSFT = "011" ) else '0' ;

 シーケンサ

  トリガーを与えられたなら、4051のマルチプレクスで
  使う(C、B、A)の3信号を出力し、1ビット情報
  をレジスタに格納します。

  トリガーを検出したなら、マルチプレクス信号出力と
  データラッチの指令を出すだけに処理を限定します。

  8ビットの情報を記憶すればよいので、シフトレジスタ
  に対する指令を出すようにコードを組みます。

      process (nRESET,CLOCK)
      begin
        if ( nRESET = '0' ) then
          iSEQ  <= 0 ;
        elsif rising_edge(CLOCK) then
          case iSEQ is
            -- wait trigger
            when 0 => if ( iTRG = '1' ) then
                        iSEQ <= 1 ;
                      else
                      iSEQ <= 0 ;
                    end if ;
          -- send address <7>
          when 1 => iSEQ <= 2 ;
          -- latch data
          when 2 => iSEQ <= 3 ;
          -- send address <6>
          when 3 => iSEQ <= 4 ;
          -- latch data
          when 4 => iSEQ <= 5 ;
          -- send address <5>
          when 5 => iSEQ <= 6 ;
          -- latch data
          when 6 => iSEQ <= 7 ;
          -- send address <4>
          when 7 => iSEQ <= 8 ;
          -- latch data
          when 8 => iSEQ <= 9 ;
          -- send address <3>
          when 9 => iSEQ <= 10 ;
          -- latch data
          when 10 => iSEQ <= 11 ;
          -- send address <2>
          when 11 => iSEQ <= 12 ;
          -- latch data
          when 12 => iSEQ <= 13 ;
          -- send address <1>
          when 13 => iSEQ <= 14 ;
          -- latch data
          when 14 => iSEQ <= 15 ;
          -- send address <0>
          when 15 => iSEQ <= 16 ;
          -- latch data
          when 16 => iSEQ <= 17 ;
          -- copy
          when 17 => iSEQ <= 18 ;
          -- return first state
          when 18 => iSEQ <= 0 ;
          -- default
          when others => iSEQ <= 0 ;
        end case ;
      end if ;
    end process ;

  4051に(C、B、A)の3信号を出力する処理と
  シフトレジスタの処理は別途定義します。

 4051制御信号生成

  4051の3信号は、シーケンサの状態値を利用して
  印加できるようにすれば充分と判断。

  VHDLコードは、以下。

      iAOUT <= "111" when ( iSEQ =  1 or iSEQ =  2 ) else
               "110" when ( iSEQ =  3 or iSEQ =  4 ) else
               "101" when ( iSEQ =  5 or iSEQ =  6 ) else
               "100" when ( iSEQ =  7 or iSEQ =  8 ) else
               "011" when ( iSEQ =  9 or iSEQ = 10 ) else
               "010" when ( iSEQ = 11 or iSEQ = 12 ) else
               "001" when ( iSEQ = 13 or iSEQ = 14 ) else
               "000" ;

  論理圧縮は、開発環境に任せてしまいます。

 4051データ入力

  4051からは、マルチプレクスの信号に合わせて1ビット
  情報が出力されてくるので、シーケンサの状態値で記憶
  します。

  シフトレジスタは、次のように定義。

      process (nRESET,CLOCK)
      begin
        if ( nRESET = '0' ) then
          iSREG <= "00000000" ;
        elsif rising_edge(CLOCK) then
          if ( iEna = '1' ) then
            iSREG <= iSREG(6 downto 0) & iDin ;
          end if ;
        end if ;
      end process ;

  シフトレジスタで、データを記憶するタイミングは
  状態値で指定するので、デコーダの出力をトリガー
  に利用。

      iEna <= '1' when ( iSEQ =  2 ) else
              '1' when ( iSEQ =  4 ) else
              '1' when ( iSEQ =  6 ) else
              '1' when ( iSEQ =  8 ) else
              '1' when ( iSEQ = 10 ) else
              '1' when ( iSEQ = 12 ) else
              '1' when ( iSEQ = 14 ) else
              '1' when ( iSEQ = 16 ) else
            '0' ;

  シーケンサの中でシフトレジスタに記憶するよりも
  見通しがよくなるので、デコーダを使っています。

 出力レジスタ

  シーケンサが取得した情報は、あるタイミングで別の
  レジスタに転送して、LEDでの目視がしやすいように
  します。ちらつきを防ぐために、シフトレジスタとは
  異なるレジスタを使います。

  シーケンサの状態値を使えば、シフトレジスタから
  レジスタへの転送タイミングがわかるので、以下と
  します。

      process (nRESET,CLOCK)
      begin
        if ( nRESET = '0' ) then
          iREG <= "00000000" ;
        elsif rising_edge(CLOCK) then
          if ( iSEQ = 17 ) then
            iREG <= iSREG ;
          end if ;
        end if ;
      end process ;

  状態値を利用することさえ決めると、大抵のテキストに
  掲載されている内容になります。

 まとめます。

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

entity t4051 is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    --
    XGTRG  : in  std_logic ;
    -- 4051
    Din    : in  std_logic ;
    AOUT   : out std_logic_vector(2 downto 0) ;
    -- monitor output
    Dout   : out std_logic_vector(7 downto 0) --;
  );
end t4051 ;

architecture behavioral of t4051 is
  --
  CONSTANT SEQ_MAX  : integer := 18 ;

  -- internal trigger
  signal iSFT : std_logic_vector(2 downto 0) ;
  signal iTRG : std_logic ;

  -- sequencer
  signal iSEQ  : integer range 0 to SEQ_MAX ;
  signal iDin  : std_logic ;
  signal iEna  : std_logic ;
  signal iSREG : std_logic_vector(7 downto 0) ;
  signal iREG  : std_logic_vector(7 downto 0) ;
  signal iAOUT : std_logic_vector(2 downto 0) ;

begin
  -- input
  iDin <= Din ;

  -- output
  AOUT <= iAOUT ;
  Dout <= iREG ;

  -- synchronizer
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSFT <= "000" ;
    elsif rising_edge(CLOCK) then
      iSFT <= iSFT(1 downto 0) & XGTRG ;
    end if ;
  end process ;
  iTRG <= '1' when ( iSFT = "011" ) else '0' ;

  -- latch data
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iREG  <= "00000000" ;
    elsif rising_edge(CLOCK) then
      if ( iSEQ = 17 ) then
        iREG <= iSREG ;
      end if ;
    end if ;
  end process ;

  -- decoder
  iAOUT <= "111" when ( iSEQ =  1 or iSEQ =  2 ) else
           "110" when ( iSEQ =  3 or iSEQ =  4 ) else
           "101" when ( iSEQ =  5 or iSEQ =  6 ) else
           "100" when ( iSEQ =  7 or iSEQ =  8 ) else
           "011" when ( iSEQ =  9 or iSEQ = 10 ) else
           "010" when ( iSEQ = 11 or iSEQ = 12 ) else
           "001" when ( iSEQ = 13 or iSEQ = 14 ) else
           "000" ;

  -- shift register
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSREG <= "00000000" ;
    elsif rising_edge(CLOCK) then
      if ( iEna = '1' ) then
        iSREG <= iSREG(6 downto 0) & iDin ;
      end if ;
    end if ;
  end process ;

  -- shift register decoder
  iEna <= '1' when ( iSEQ =  2 ) else
          '1' when ( iSEQ =  4 ) else
          '1' when ( iSEQ =  6 ) else
          '1' when ( iSEQ =  8 ) else
          '1' when ( iSEQ = 10 ) else
          '1' when ( iSEQ = 12 ) else
          '1' when ( iSEQ = 14 ) else
          '1' when ( iSEQ = 16 ) else
          '0' ;

  -- sequencer
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSEQ  <= 0 ;
    elsif rising_edge(CLOCK) then
      case iSEQ is
        -- wait trigger
        when 0 => if ( iTRG = '1' ) then
                    iSEQ <= 1 ;
                  else
                    iSEQ <= 0 ;
                  end if ;
        -- send address <7>
        when 1 => iSEQ <= 2 ;
        -- latch data
        when 2 => iSEQ <= 3 ;
        -- send address <6>
        when 3 => iSEQ <= 4 ;
        -- latch data
        when 4 => iSEQ <= 5 ;
        -- send address <5>
        when 5 => iSEQ <= 6 ;
        -- latch data
        when 6 => iSEQ <= 7 ;
        -- send address <4>
        when 7 => iSEQ <= 8 ;
        -- latch data
        when 8 => iSEQ <= 9 ;
        -- send address <3>
        when 9 => iSEQ <= 10 ;
        -- latch data
        when 10 => iSEQ <= 11 ;
        -- send address <2>
        when 11 => iSEQ <= 12 ;
        -- latch data
        when 12 => iSEQ <= 13 ;
        -- send address <1>
        when 13 => iSEQ <= 14 ;
        -- latch data
        when 14 => iSEQ <= 15 ;
        -- send address <0>
        when 15 => iSEQ <= 16 ;
        -- latch data
        when 16 => iSEQ <= 17 ;
        -- copy
        when 17 => iSEQ <= 18 ;
        -- return first state
        when 18 => iSEQ <= 0 ;
        -- default
        when others => iSEQ <= 0 ;
      end case ;
    end if ;
  end process ;

end behavioral;

 ピンアサインは、次のように指定。

# system
NET "CLOCK"  LOC = "P5" ;
NET "nRESET" LOC = "P39" ;

# 4051
NET "Din"      LOC = "P1" ;
NET "AOUT<0>"  LOC = "P2" ;
NET "AOUT<1>"  LOC = "P3" ;
NET "AOUT<2>"  LOC = "P4" ;

# monitor
NET "Dout<0>" LOC = "P11" ;
NET "Dout<1>" LOC = "P12" ;
NET "Dout<2>" LOC = "P13" ;
NET "Dout<3>" LOC = "P14" ;
NET "Dout<4>" LOC = "P18" ;
NET "Dout<5>" LOC = "P19" ;
NET "Dout<6>" LOC = "P20" ;
NET "Dout<7>" LOC = "P22" ;

# tirgger
NET "XGTRG" LOC = "P24" ;


目次

inserted by FC2 system