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" ;
目次
前
次