FC2カウンター FPGAの部屋 ZedBoard AXI4 Lite Slave 演習7(VHDLバージョンの作製)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ZedBoard AXI4 Lite Slave 演習7(VHDLバージョンの作製)

ZedBoard AXI4 Lite Slave 演習6(Cソース・ファイルの公開)”の続き。

前回までの AXI4 Lite Slave カスタムIPは、Verilog HDLで書かれていたので、VHDL版を用意する必要がある。今度は、VHDL版を作製しシミュレーションを行った。

下にシミュレーション用のProject Navigator のプロジェクトを示す。
AXI4_practice_23_131223.png

led8_axi_lite_slave.vhd は VHDL で書かれているが、その他のシミュレーション用ファイルは Verilog HDLのままとした。
下にシミュレーション結果を示す。
AXI4_practice_24_131223.png

led8_axi_lite_slave.vhd の VHDL ソース・ファイルを下に示す。

-----------------------------------------------------------------------------
--
-- AXI Lite Slave
--
-- led8_axi_lite_slave
--
-- LED 8bitを制御する
-----------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

--library unisim;
--use unisim.vcomponents.all;

entity led8_axi_lite_slave is
  generic (
    C_S_AXI_ADDR_WIDTH   : integer := 32;
    C_S_AXI_DATA_WIDTH   : integer := 32
    );
  port(
    -- System Signals
    ACLK    : in std_logic;
    ARESETN : in std_logic;

    -- Slave Interface Write Address Ports
    S_AXI_AWADDR   : in  std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
    S_AXI_AWPROT   : in  std_logic_vector(3-1 downto 0);
    S_AXI_AWVALID  : in  std_logic;
    S_AXI_AWREADY  : out std_logic;

    -- Slave Interface Write Data Ports
    S_AXI_WDATA  : in  std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
    S_AXI_WSTRB  : in  std_logic_vector(C_S_AXI_DATA_WIDTH/8-1 downto 0);
    S_AXI_WVALID : in  std_logic;
    S_AXI_WREADY : out std_logic;

    -- Slave Interface Write Response Ports
    S_AXI_BRESP  : out std_logic_vector(2-1 downto 0);
    S_AXI_BVALID : out std_logic;
    S_AXI_BREADY : in  std_logic;

    -- Slave Interface Read Address Ports
    S_AXI_ARADDR   : in  std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
    S_AXI_ARPROT   : in  std_logic_vector(3-1 downto 0);
    S_AXI_ARVALID  : in  std_logic;
    S_AXI_ARREADY  : out std_logic;

    -- Slave Interface Read Data Ports
    S_AXI_RDATA  : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
    S_AXI_RRESP  : out std_logic_vector(2-1 downto 0);
    S_AXI_RVALID : out std_logic;
    S_AXI_RREADY : in  std_logic;

    -- User Signals
    LED8bit : out std_logic_vector(7 downto 0)
    );

end led8_axi_lite_slave;

architecture implementation of led8_axi_lite_slave is
-- RESP の値の定義
constant RESP_OKAY :    std_logic_vector := "00";
constant RESP_EXOKAY :  std_logic_vector := "01";
constant RESP_SLVERR :  std_logic_vector := "10";
constant RESP_DECERR :  std_logic_vector := "11";

-- Write Transaction State Machine
type WRITE_TRAN_SM is (IDLE_WR, DATA_WIRTE_HOLD, BREADY_ASSERT);
signal wrt_cs : WRITE_TRAN_SM;

-- Read Transaction State Machine
type READ_TRAN_SM is (IDLE_RD, RDATA_WAIT);
signal rdt_cs : READ_TRAN_SM;

-- Registers
signal Commannd_Register :      std_logic_vector(31 downto 0);
signal Counter_Load_Register :  std_logic_vector(31 downto 0);
signal LED_Interval_Resgister : std_logic_vector(31 downto 0);

-- Counters
signal LED_Display_Counter :    std_logic_vector(7 downto 0);
signal LED_Interval_Counter :   std_logic_vector(31 downto 0);

signal awready :        std_logic := '1';
signal bvalid :         std_logic := '0';
signal arready :        std_logic := '1';
signal rvalid :         std_logic := '0';
signal rdata :          std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal awaddr_hold :    std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal wready :         std_logic;

begin
    ---- Write Transaction
    -- AXI4 Lite Slave Write Transaction State Machine (Address, Response)
    proc_Write_Tran_SM : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN = '0' then
                wrt_cs <= IDLE_WR;
                awready <= '1';
                bvalid <= '0';
                awaddr_hold <= (others => '0');
                wready <= '0';
            else
                case wrt_cs is
                    when IDLE_WR =>
                        if S_AXI_AWVALID = '1' then -- Write Transaction Start
                            wrt_cs <= DATA_WIRTE_HOLD;
                            awready <= '0';
                            awaddr_hold <= S_AXI_AWADDR;
                            wready <= '1';
                        end if;
                    when DATA_WIRTE_HOLD =>
                        if S_AXI_WVALID = '1' then -- Write data just valid
                            wrt_cs <= BREADY_ASSERT;
                            bvalid <= '1';
                            wready <= '0';
                        end if;
                    when BREADY_ASSERT =>
                        if S_AXI_BREADY = '1' then -- The write transaction was terminated.
                            wrt_cs <= IDLE_WR;
                            bvalid <= '0';
                            awready <= '1';
                        end if;
                end case;
            end if;
        end if;
    end process proc_Write_Tran_SM;
    S_AXI_AWREADY <= awready;
    S_AXI_BVALID <= bvalid;
    S_AXI_BRESP <= RESP_OKAY;
    S_AXI_WREADY <= wready;

    ---- Read Transaction
    -- AXI4 Lite Slave Read Transaction State Machine
    proc_Read_Tran_SM : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN = '0' then
                rdt_cs <= IDLE_RD;
                arready <= '1';
                rvalid <= '0';
            else
                case rdt_cs is
                    when IDLE_RD =>
                        if S_AXI_ARVALID = '1' then
                            rdt_cs <= RDATA_WAIT;
                            arready <= '0';
                            rvalid <= '1';
                        end if;
                    when RDATA_WAIT =>
                        if S_AXI_RREADY = '1' then
                            rdt_cs <= IDLE_RD;
                            arready <= '1';
                            rvalid <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process proc_Read_Tran_SM;
    S_AXI_ARREADY <= arready;
    S_AXI_RVALID <= rvalid;
    S_AXI_RRESP <= RESP_OKAY;

    -- S_AXI_RDATA
    proc_RDATA : process (ACLK) begin
        if ARESETN = '0' then
            rdata <= (others => '0');
        elsif S_AXI_ARVALID = '1' then
            case S_AXI_ARADDR(3 downto 0) is
                when x"0" => rdata <= Commannd_Register;
                when x"4" => rdata <= Counter_Load_Register;
                when x"8" => rdata(31 downto 8) <= x"000000";
                                    rdata(7 downto 0) <= LED_Display_Counter;
                when x"c" => rdata <= LED_Interval_Resgister;
                     when others => 
            end case;
        end if;
    end process proc_RDATA;
    S_AXI_RDATA <= rdata;

    ---- Registeres
    -- Commannd_Register
    -- オフセット0:Command Register(R/W)
    -- ビット0:1 - LEDの値を+1する 0 - LEDの値はそのまま (デフォルト値は0)
    -- ビット31〜1:リザーブ
    proc_Commannd_Register : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN = '0' then
                Commannd_Register <= (others => '0');
            else
                if S_AXI_WVALID='1' and wready='1' and awaddr_hold(3 downto 0)=x"0" then
                    Commannd_Register(0) <= S_AXI_WDATA(0);
                end if;
            end if;
        end if;
    end process proc_Commannd_Register;

    -- Counter_Load_Register
    -- オフセット4:LED Counter Load Register(R/W)
    -- ビット7〜0:8ビット分のLEDの値
    -- ビット31〜8:リザーブ(Read時はすべて0)
    proc_Counter_Load_Register : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN = '0' then
                Counter_Load_Register <= (others => '0');
            else
                if S_AXI_WVALID='1' and wready='1' and awaddr_hold(3 downto 0)=x"4" then
                    Counter_Load_Register(7 downto 0) <= S_AXI_WDATA(7 downto 0);
                end if;
            end if;
        end if;
    end process proc_Counter_Load_Register;

    -- LED_Interval_Resgister
    -- オフセットC:LED Interval Register(R/W)但し、動作クロックは100MHzとする
    -- ビット31〜0:LED値を+1する時のカウント値
    proc_LED_Interval_Resgister : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN = '0' then
                LED_Interval_Resgister <= (others => '0');
            else
                if S_AXI_WVALID='1' and wready='1' and awaddr_hold(3 downto 0)=x"C" then
                    LED_Interval_Resgister <= S_AXI_WDATA;
                end if;
            end if;
        end if;
    end process proc_LED_Interval_Resgister;

    ---- Conteres
    -- LED_Display_Counter
    proc_LED_Display_Counter : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN='0' then
                LED_Display_Counter <= (others => '0');
            else
                if S_AXI_WVALID='1' and wready='1' and awaddr_hold(3 downto 0)=x"4" then -- Counter Load
                    LED_Display_Counter <= S_AXI_WDATA(7 downto 0);
                elsif Commannd_Register(0) = '1' then -- Enable
                    if LED_Interval_Counter = x"00000000" then 
                        LED_Display_Counter <=  std_logic_vector(unsigned(LED_Display_Counter) + 1);
                    end if;
                end if;
            end if;
        end if;
    end process proc_LED_Display_Counter;
    LED8bit <= LED_Display_Counter;

    -- LED_Interval_Counter
    proc_LED_Interval_Counter : process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if ARESETN='0' then
                LED_Interval_Counter <= (others => '0');
            else
                if Commannd_Register(0) = '1' then -- Enable
                    if LED_Interval_Counter = x"00000000" then
                        LED_Interval_Counter <= LED_Interval_Resgister;
                    else
                        LED_Interval_Counter <= std_logic_vector(unsigned(LED_Interval_Counter) - 1);
                    end if;
                else
                    LED_Interval_Counter <= LED_Interval_Resgister;
                end if;
            end if;
        end if;
    end process proc_LED_Interval_Counter;

end implementation;

  1. 2013年12月23日 05:12 |
  2. AXI4バスの演習資料
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2683-43362b37
この記事にトラックバックする(FC2ブログユーザー)