目次

FIFO

 FIFO(First In First out)は、スタックの逆動作を
 するメカニズムです。



 10usごとに変化するデータを、逐次SRAMに保存する
 計測回路を要求されたので、SRAMアクセスとデータ
 取得の同期をとるため、FIFOを利用しました。

 内部は、次のように構成しました。



 3つの4ビットレジスタをカスケード接続して
 12ビットのレジスタひとつで表現して扱います。

  signal iSREG : std_logic_vector(11 downto 0) ;

 10usごとに、4ビットずつ値を更新すれば
 FIFOが完成します。

 初期化を含め、コード記述は、以下となります。

  process (nRESET,iCLK)
  begin
    if ( nRESET = '0' ) then
      iSREG <= X"000" ;
    elsif rising_edge( iCLK ) then
      iSREG(11 downto 8) <= iSREG(7 downto 4) ;
      iSREG( 7 downto 4) <= iSREG(3 downto 0) ;
      iSREG( 3 downto 0) <= XDin ;
    end if ;
  end process ;

 シフトレジスタを動かすためのクロックが
 必要になるので、分周回路を使い生成します。
 システムクロックを4MHzとして次のように
 定義します。

  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= 0 ;
    elsif rising_edge( CLOCK ) then
      if ( iCNT = CNTMAX ) then
        iCNT <= 0 ;
      else
        iCNT <= iCNT + 1 ;
      end if ;
    end if ;
  end process ;
  iCLK <= '1' when ( iCNT < CNTHALF ) else '0' ; -- 100kHz

 2つのprocess文を、合体するとFIFOができあがり
 ますが、デバッグすることを考えて、4ビットごと
 にモニタ出力する回路をつけます。



 セレクタにより、任意の4ビットを出力すれば
 よいので、データセレクタを定義します。

  FOUT <= iSREG( 7 downto 4) when ( iSEL = "01" ) else
          iSREG( 3 downto 0) when ( iSEL = "10" ) else
          iSREG(11 downto 8) ;

 まとめると以下。

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

entity tstsreg is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ; -- 4MHz
    -- data in 
    XDin   : in  std_logic_vector(3 downto 0) ;
    -- data out 
    XDout  : out std_logic_vector(3 downto 0) ;
    -- selector 
    SEL    : in  std_logic_vector(1 downto 0) ;
    -- monitor out
    FOUT : out std_logic_vector(3 downto 0) -- ;
  );
end tstsreg ;

architecture behavioral of tstsreg is
  CONSTANT CNTMAX  : integer := 39 ;
  CONSTANT CNTHALF : integer := 20 ;
  -- generate 100kHz
  signal iCLK  : std_logic ;
  signal iCNT  : integer range 0 to CNTMAX ;
  -- internal register
  signal iSREG : std_logic_vector(11 downto 0) ;
  -- selector
  signal iSEL  : std_logic_vector(1 downto 0) ;
begin
  -- input
  iSEL <= SEL ;

  -- output
  XDout <= iSREG(11 downto 8) ;

  -- monitor output
  FOUT <= iSREG( 7 downto 4) when ( iSEL = "01" ) else
          iSREG( 3 downto 0) when ( iSEL = "10" ) else
          iSREG(11 downto 8) ;

  -- generate 100kHz
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= 0 ;
    elsif rising_edge( CLOCK ) then
      if ( iCNT = CNTMAX ) then
        iCNT <= 0 ;
      else
        iCNT <= iCNT + 1 ;
      end if ;
    end if ;
  end process ;
  iCLK <= '1' when ( iCNT < CNTHALF ) else '0' ; -- 100kHz

  -- shift register
  process (nRESET,iCLK)
  begin
    if ( nRESET = '0' ) then
      iSREG <= X"000" ;
    elsif rising_edge( iCLK ) then
      iSREG(11 downto 8) <= iSREG(7 downto 4) ;
      iSREG( 7 downto 4) <= iSREG(3 downto 0) ;
      iSREG( 3 downto 0) <= XDin ;
    end if ;
  end process ;

end behavioral;

 ピンアサインは、XC9572を使うとして
 次のように設定しました。

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

# data input and output
NET "XDout<0>" LOC = "P1" ;
NET "XDout<1>" LOC = "P2" ;
NET "XDout<2>" LOC = "P3" ;
NET "XDout<3>" LOC = "P4" ;
NET "XDin<0>"  LOC = "P6" ;
NET "XDin<1>"  LOC = "P7" ;
NET "XDin<2>"  LOC = "P8" ;
NET "XDin<3>"  LOC = "P9" ;

# monitor output
NET "FOUT<0>" LOC = "P11" ;
NET "FOUT<1>" LOC = "P12" ;
NET "FOUT<2>" LOC = "P13" ;
NET "FOUT<3>" LOC = "P14" ;
NET "SEL<0>"  LOC = "P18" ;
NET "SEL<1>"  LOC = "P19" ;

 4ビットレジスタを3個使う場合
 XC9572では、利用マクロセル数は31
 でした。

 4ビットレジスタを4個にしても、増える
 マクロセル数は4だけなので、16ビットの
 レジスタを利用する処理で記述してみます。

 VHDLコードは、以下。

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

entity tstsreg is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ; -- 4MHz
    -- data in 
    XDin   : in  std_logic_vector(3 downto 0) ;
    -- data out 
    XDout  : out std_logic_vector(3 downto 0) ;
    -- selector 
    SEL    : in  std_logic ;
    -- monitor out
    FOUT : out std_logic_vector(7 downto 0) -- ;
  );
end tstsreg ;

architecture behavioral of tstsreg is
  CONSTANT CNTMAX  : integer := 39 ;
  CONSTANT CNTHALF : integer := 20 ;
  -- generate 100kHz
  signal iCLK  : std_logic ;
  signal iCNT  : integer range 0 to CNTMAX ;
  -- internal register
  signal iSREG : std_logic_vector(15 downto 0) ;
  -- selector
  signal iSEL  : std_logic ;
begin
  -- input
  iSEL <= SEL ;

  -- output
  XDout <= iSREG(15 downto 12) ;

  -- monitor output
  FOUT <= iSREG( 7 downto 0) when ( iSEL = '1' ) else
          iSREG(15 downto 8) ;

  -- generate 100kHz
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= 0 ;
    elsif rising_edge( CLOCK ) then
      if ( iCNT = CNTMAX ) then
        iCNT <= 0 ;
      else
        iCNT <= iCNT + 1 ;
      end if ;
    end if ;
  end process ;
  iCLK <= '1' when ( iCNT < CNTHALF ) else '0' ; -- 100kHz

  -- shift register
  process (nRESET,iCLK)
  begin
    if ( nRESET = '0' ) then
      iSREG <= X"0000" ;
    elsif rising_edge( iCLK ) then
      iSREG(15 downto 12) <= iSREG(11 downto 8) ;
      iSREG(11 downto  8) <= iSREG( 7 downto 4) ;
      iSREG( 7 downto  4) <= iSREG( 3 downto 0) ;
      iSREG( 3 downto  0) <= XDin ;
    end if ;
  end process ;

end behavioral;

 16ビットレジスタにしたので、モニター出力を
 8ビットにしてあります。セレクタのビット数
 を1に減らせるので、セレクタの定義が単純に
 なりました。



 XC9572を利用した、ピンアサインは以下。

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

# data input and output
NET "XDout<0>" LOC = "P1" ;
NET "XDout<1>" LOC = "P2" ;
NET "XDout<2>" LOC = "P3" ;
NET "XDout<3>" LOC = "P4" ;
NET "XDin<0>"  LOC = "P6" ;
NET "XDin<1>"  LOC = "P7" ;
NET "XDin<2>"  LOC = "P8" ;
NET "XDin<3>"  LOC = "P9" ;

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

# selector
NET "SEL"  LOC = "P24" ;


目次

inserted by FC2 system