FC2カウンター FPGAの部屋 2013年11月
fc2ブログ

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

FPGAの部屋

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

AXI4 Master アクセスのラプラシアン・フィルタ IP8(インプリメント2、実機テスト)

AXI4 Master アクセスのラプラシアン・フィルタ IP7(インプリメント1)”の続き。

・XPSプロジェクトで、Generate Netlistが終了した。今度は、system_lap_filter_axim_0_wapper のLUT使用率が586になっていて良い感じだ。
axi4m_lap_filter_28_131129.png

・Poject Navigator に戻って、論理合成、インプリメント、ビットストリームの生成を行った。成功した。
axi4m_lap_filter_30_131130.png

・FPGA Editor を立ちあげて、lap_filter_axim_0 を見ると、lap_filter_axim_LiteS_if_Uがあった。これで一安心。
axi4m_lap_filter_29_131130.png

・SDKを立ちあげ、SDカードに入れるブートイメージを作製した。

・BOOT.bin をSDカードに入れて、Linuxをブート。

・lap_filte_axim のデバック・コンフィギュレーションを作って、デバック。(手順はかなり省略しています。詳しい手順は、”Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う2”をどうぞ)

・まずは、ソフトコアで作ったラプラシアン・フィルタ・ソフトウェアを起動して実行した。(詳しくは、”ソフトウエアのプロファイリング4(ハードウェアと同じ方式)”をどうぞ)
axi4m_lap_filter_34_131130.jpg

・lap_filte_axim を実行するソフトウェアを実行すると、下の写真のようになった。
axi4m_lap_filter_35_131130.jpg

・画面の1/4しか、書き込んでいないみたいだ。ショック。。。

・ChipScope Pro を仕掛けておいたので、起動した。下に、WVAILD の立ち上がりでトリガを掛けた時の波形を示す。
axi4m_lap_filter_31_131130.png

・Write Address Channel を拡大してみた。なにかおかしい?
axi4m_lap_filter_32_131130.png

・Read Address Channel を拡大すると理由がわかった。Write Address Channel のアドレス増加ステップがデータバス幅 32/8 = 4 ではなくて、1 だ。
axi4m_lap_filter_33_131130.png

HDLコードの Writeアドレスの増加ステップがおかしかったので、修正を行った。
  1. 2013年11月30日 13:11 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP7(インプリメント1)

AXI4 Master アクセスのラプラシアン・フィルタ IP6(line_read_and_y.v と Dual_Port_Memory.v)”の続き。

今回は、MPDファイルやPAOファイルを作って、カスタムIPとしてXPSプロジェクトにADD IPして、ISEから論理合成、インプリメントを行った。

・まずは、XPSプロジェクトに lap_filter_axim IP をADD IPした。
axi4m_lap_filter_16_131126.png

・Portsタブでクロックを接続。
axi4m_lap_filter_17_131126.png

・Addressesタブで、アドレスを 0x4A000000 に設定
axi4m_lap_filter_18_131126.png

・Project Navigator に戻って、論理合成、インプリメント、ビットストリームの生成を行った。成功した。
axi4m_lap_filter_19_131126.png

・試しに、FPGA Editor で見てみると、lap_filter_axim_0 のロジックが大幅に少ない。lap_filter_axim_LiteS_if.v は消去されていた。
axi4m_lap_filter_21_131128.png

・試しにVivado HLS で生成した lap_filter_axim_top_0 を Delete して、XPSプロジェクトで Hardware メニューから Generate Netlistをやってみた。
axi4m_lap_filter_22_131129.png

・Summary を見ると、system_lap_filter_axim_0_wapper に使用リソースが少ない。
axi4m_lap_filter_23_131129.png

・system_lap_filter_axim_0_wapper をクリックすると、XSTのログが出る。そこで、s_axi_lite_wstrb が接続されていないという WARNING が出ていた。
axi4m_lap_filter_24_131129.png

WARNING:Xst:2898 - Port 's_axi_lite_wstrb', unconnected in block instance 'lap_filter_axim_0', is tied to GND.


・Portsタブで確認すると確かに、s_axi_lite_wstrb が接続されていない。
axi4m_lap_filter_25_131129.png

・lap_filter_axim_v2_1_0.mpd ファイルを見ると、s_axi_lite_wstrb の定義が書いていない。これは、ビットマップ・ディスプレイ・コントローラから持ってきたのだが、そこでは、s_axi_lite_wstrb は使っていなかった。

## AXI4 Lite Slave Ports
PORT s_axi_lite_awvalid = AWVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_awready = AWREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_awaddr = AWADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wvalid = WVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_wready = WREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_wdata = WDATA, DIR = I, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bresp = BRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bvalid = BVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_bready = BREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arvalid = ARVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arready = ARREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_araddr = ARADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rvalid = RVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_rready = RREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_rdata = RDATA, DIR = O, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rresp = RRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE


・s_axi_lite_wstrb の定義をMPDファイルに追加した。

## AXI4 Lite Slave Ports
PORT s_axi_lite_awvalid = AWVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_awready = AWREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_awaddr = AWADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wvalid = WVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_wready = WREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_wdata = WDATA, DIR = I, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wstrb = WSTRB, DIR = I, VEC = [((C_S_AXI_LITE_DATA_WIDTH/8)-1):0], ENDIAN = LITTLE, BUS = S_AXI_LITE
PORT s_axi_lite_bresp = BRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bvalid = BVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_bready = BREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arvalid = ARVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arready = ARREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_araddr = ARADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rvalid = RVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_rready = RREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_rdata = RDATA, DIR = O, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rresp = RRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE


・Project メニューから Rescan User Repositories を行うと、s_axi_lite_wstrb が見えた。
axi4m_lap_filter_27_131129.png

・これで、もう一度、 Hardware メニューから Generate Netlistを行った。

今、 Generate Netlistを行っている最中です。結果は次回のブログでお知らせします。
  1. 2013年11月29日 04:43 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP6(line_read_and_y.v と Dual_Port_Memory.v)

AXI4 Master アクセスのラプラシアン・フィルタ IP6(lap_filter_axim_LiteS_if.v のHDLソース)”の続き。

今回は、下位モジュールの line_read_and_y.v と Dual_Port_Memory.v を貼っておく。

line_read_and_y.v は、HORIZONTAL_PIXELS 分のピクセルデータを start_addr から AXI4 Master Readして、RGB - Y変換を行い、y_data へ出力する下位モジュールだ。
line_read_and_y.v を下に貼る。

`default_nettype none

//
// line_read_and_y.v
// HORIZONTAL_PIXELS 分のピクセルデータを start_addr から AXI4 Master Read する
// RGB - Y変換を行い、y_data へ出力する
// 2013/11/17
//

module line_read_and_y #(
    parameter    integer    C_M_AXI_ADDR_WIDTH        = 32,
    parameter    integer    C_M_AXI_DATA_WIDTH        = 32,
    parameter     integer    HORIZONTAL_PIXELS        = 800
)
(
    input    wire                                clk,
    input    wire                                reset,
    input    wire    [C_M_AXI_ADDR_WIDTH-1:0]    start_addr,
    input    wire                                start,
    output    reg                                    done,
    output    reg        [7:0]                        y_data,
    output    reg                                    y_data_valid,

    output    wire                                read_adfifo_wr_ena,
    output    reg        [C_M_AXI_ADDR_WIDTH-1:0]    read_adfifo_addr,
    output    reg        [8-1:0]                        read_adfifo_arlen,
    input    wire                                read_adfifo_full,

    output    wire                                 read_fifo_rd_ena,
    input    wire    [C_M_AXI_DATA_WIDTH-1:0]    read_fifo_read_data,
    input    wire                                read_fifo_empty_n,
    input    wire                                read_fifo_almost_empty_n
);

    // Beyond Circuts, Constant Function in Verilog 2001を参照しました
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction

    reg        [log2(HORIZONTAL_PIXELS)-1:0]    h_addr_cnt;

    parameter     IDLE_READ_ADDR =    1'b0,
                READ_ADDR_ACTIVE =     1'b1;
    reg        read_addr_req_cs;
    wire    [log2(HORIZONTAL_PIXELS)-1:0]    BURST_LIMIT_VAL = 256;
    wire    [log2(HORIZONTAL_PIXELS)-1:0]    ONE = 1;
    reg        op_state;
    reg        [log2(HORIZONTAL_PIXELS)-1:0]    y_data_cnt;


    // start が来たら op_state を1にする。全部のReadデータを受け取った時に0にする
    always @(posedge clk) begin : proc_op_state
       if(reset) begin
            op_state <= 1'b0;
       end else begin
               if (start)
                   op_state <= 1'b1;
               else if (y_data_cnt==ONE && y_data_valid==1'b1)
                   op_state <= 1'b0;
       end
    end

    // Read Address Transaction State Machine
    always @(posedge clk) begin : proc_Read_Addr_Tran_SM
       if(reset) begin
            read_addr_req_cs <= IDLE_READ_ADDR;
       end else begin
               case (read_addr_req_cs)
                   IDLE_READ_ADDR :
                       if (read_adfifo_full==1'b0 && h_addr_cnt!=0 && op_state==1'b1)
                           read_addr_req_cs <= READ_ADDR_ACTIVE;
                   READ_ADDR_ACTIVE :
                       read_addr_req_cs <= IDLE_READ_ADDR;

                  default : /* default */;
               endcase
       end
    end
    assign read_adfifo_wr_ena = (read_addr_req_cs==READ_ADDR_ACTIVE) ? 1'b1 : 1'b0;

    // h_addr_cnt の処理
    always @(posedge clk) begin : proc_h_addr_cnt
       if(reset) begin
            h_addr_cnt <= HORIZONTAL_PIXELS;
            read_adfifo_arlen <= 8'd0;
       end else begin
               if (start) begin
                   h_addr_cnt <= HORIZONTAL_PIXELS;
            end else if (h_addr_cnt!=0 && read_addr_req_cs==IDLE_READ_ADDR && read_adfifo_full==1'b0 && op_state==1'b1) begin
                if (h_addr_cnt>=BURST_LIMIT_VAL) begin
                    h_addr_cnt <= h_addr_cnt - BURST_LIMIT_VAL;
                    read_adfifo_arlen <= 8'd255;
                end else begin
                    h_addr_cnt <= 0;
                    read_adfifo_arlen <= h_addr_cnt[7:0] - 8'd1;
                end
            end
       end
    end

    // read_adfifo_addr の処理
    always @(posedge clk) begin : proc_read_adfifo_addr
       if(reset) begin
            read_adfifo_addr <= 0;
       end else begin
               if (start)
                   read_adfifo_addr <= start_addr;
            else if (read_addr_req_cs == READ_ADDR_ACTIVE)
                read_adfifo_addr <= read_adfifo_addr + (read_adfifo_arlen+8'd1)*(C_M_AXI_DATA_WIDTH/8);
       end
    end

    // RGBからYへの変換
    // RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
    // 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
    // "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
    always @(posedge clk) begin : proc_RGB2Y
        reg [15:0]    y_f;
        reg [7:0]    b, g, r;

       if(reset) begin
            y_data <= 8'd0;
       end else begin
               r = read_fifo_read_data[23:16];
               g = read_fifo_read_data[15:0];
               b = read_fifo_read_data[7:0];

               y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
               y_data <= y_f[15:8];    // 256で割る
       end
    end

    // y_data_valid の処理
    always @(posedge clk) begin : proc_y_data_valid
       if(reset) begin
            y_data_valid <= 1'b0;
       end else begin
            if (read_fifo_empty_n)
                y_data_valid <= 1'b1;
            else
                y_data_valid <= 1'b0;
       end
    end

    assign read_fifo_rd_ena = 1'b1;

    // y_data のカウント
    always @(posedge clk) begin : proc_y_data_cnt
       if(reset) begin
            y_data_cnt <= HORIZONTAL_PIXELS;
       end else begin
               if (op_state==1'b1 && y_data_valid==1'b1 && y_data_cnt!=0)
                   y_data_cnt <= y_data_cnt - ONE;
               else if (start)
                   y_data_cnt <= HORIZONTAL_PIXELS;
       end
    end

    // done の処理
    always @(posedge clk) begin : proc_done
       if(reset) begin
            done <= 1'b0;
       end else begin
               if (y_data_cnt==ONE && y_data_valid==1'b1)
                   done <= 1'b1;
               else
                   done <= 1'b0;
       end
    end
endmodule

`default_nettype wire


次は、 Dual_Port_Memory.v だが、これは、”XST に Dual Port Memory を推論させる (Verilog HDL)”の Dual_Port_Memory_test.v と同じだが、モジュール名を変更したので、もう一度、貼っておく。

`default_nettype none

module Dual_Port_Memory #(
  parameter integer C_MEMORY_SIZE =   1024, // Word Memory Size (not byte)
  parameter integer DATA_BUS_WIDTH =  32    // RAM Data Width
)
(
    input  wire clk,
    input  wire we,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   waddr,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   raddr,
    input  wire [DATA_BUS_WIDTH-1:0]  din,
    output reg  [DATA_BUS_WIDTH-1:0]  dout
);

    // Beyond Circuts, Constant Function in Verilog 2001を参照しました
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction

    reg  [DATA_BUS_WIDTH-1:0]  ram  [0:C_MEMORY_SIZE-1];

    initial begin : memory_initialize
        integer i;
        for (i=0; i<C_MEMORY_SIZE; i=i+1)
            ram[i] = 0;
    end

    always  @(posedge  clk) begin
        if  (we)
            ram[waddr]  <=  din;

        dout  <=  ram[raddr];
    end

endmodule

`default_nettype wire

  1. 2013年11月28日 05:04 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP6(lap_filter_axim_LiteS_if.v のHDLソース)

AXI4 Master アクセスのラプラシアン・フィルタ IP5(lap_filter_axim.v のHDLソース)”の続き。

今回は、Vivado HLSでラプラシアン・フィルタ AXI Master IP を作った際のAXI4 Lite Slave モジュール lap_filter_axim_LiteS_if.v を貼っておく。

// ==============================================================
// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
// Version: 2013.3
// Copyright (C) 2013 Xilinx Inc. All rights reserved.
// 
// ==============================================================

`timescale 1ns/1ps
module lap_filter_axim_LiteS_if
#(parameter
    C_ADDR_WIDTH = 6,
    C_DATA_WIDTH = 32
)(
    // axi4 lite slave signals
    input  wire                      ACLK,
    input  wire                      ARESETN,
    input  wire [C_ADDR_WIDTH-1:0]   AWADDR,
    input  wire                      AWVALID,
    output wire                      AWREADY,
    input  wire [C_DATA_WIDTH-1:0]   WDATA,
    input  wire [C_DATA_WIDTH/8-1:0] WSTRB,
    input  wire                      WVALID,
    output wire                      WREADY,
    output wire [1:0]                BRESP,
    output wire                      BVALID,
    input  wire                      BREADY,
    input  wire [C_ADDR_WIDTH-1:0]   ARADDR,
    input  wire                      ARVALID,
    output wire                      ARREADY,
    output wire [C_DATA_WIDTH-1:0]   RDATA,
    output wire [1:0]                RRESP,
    output wire                      RVALID,
    input  wire                      RREADY,
    output wire                      interrupt,
    // user signals
    output wire [31:0]               I_cam_addr,
    output wire                      I_cam_addr_ap_vld,
    input  wire                      I_cam_addr_ap_ack,
    output wire [31:0]               I_lap_addr,
    output wire                      I_lap_addr_ap_vld,
    output wire                      I_ap_start,
    input  wire                      O_ap_ready,
    input  wire                      O_ap_done,
    input  wire                      O_ap_idle,
    input  wire [31:0]               O_ap_return
);
//------------------------Address Info-------------------
// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/COH)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved
// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x10 : Control signal of cam_addr
//        bit 0  - cam_addr_ap_vld (Read/Write/COH)
//        bit 1  - cam_addr_ap_ack (Read)
//        others - reserved
// 0x14 : Data signal of cam_addr
//        bit 31~0 - cam_addr[31:0] (Read/Write)
// 0x18 : Control signal of lap_addr
//        bit 0  - lap_addr_ap_vld (Read/Write/SC)
//        others - reserved
// 0x1c : Data signal of lap_addr
//        bit 31~0 - lap_addr[31:0] (Read/Write)
// 0x20 : Data signal of ap_return
//        bit 31~0 - ap_return[31:0] (Read)
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)

//------------------------Parameter----------------------
// address bits
localparam
    ADDR_BITS = 6;

// address
localparam
    ADDR_AP_CTRL         = 6'h00,
    ADDR_GIE             = 6'h04,
    ADDR_IER             = 6'h08,
    ADDR_ISR             = 6'h0c,
    ADDR_CAM_ADDR_CTRL   = 6'h10,
    ADDR_CAM_ADDR_DATA_0 = 6'h14,
    ADDR_LAP_ADDR_CTRL   = 6'h18,
    ADDR_LAP_ADDR_DATA_0 = 6'h1c,
    ADDR_AP_RETURN_0     = 6'h20;

// axi write fsm
localparam
    WRIDLE = 2'd0,
    WRDATA = 2'd1,
    WRRESP = 2'd2;

// axi read fsm
localparam
    RDIDLE = 2'd0,
    RDDATA = 2'd1;

//------------------------Local signal-------------------
// axi write
reg  [1:0]           wstate;
reg  [1:0]           wnext;
reg  [ADDR_BITS-1:0] waddr;
wire [31:0]          wmask;
wire                 aw_hs;
wire                 w_hs;
// axi read
reg  [1:0]           rstate;
reg  [1:0]           rnext;
reg  [31:0]          rdata;
wire                 ar_hs;
wire [ADDR_BITS-1:0] raddr;
// internal registers
wire                 ap_idle;
reg                  ap_done;
wire                 ap_ready;
reg                  ap_start;
reg                  auto_restart;
reg                  gie;
reg  [1:0]           ier;
reg  [1:0]           isr;
reg  [31:0]          _cam_addr;
reg                  _cam_addr_ap_vld;
wire                 _cam_addr_ap_ack;
reg  [31:0]          _lap_addr;
reg                  _lap_addr_ap_vld;
wire [31:0]          ap_return;

//------------------------Body---------------------------
//++++++++++++++++++++++++axi write++++++++++++++++++++++
assign AWREADY = (wstate == WRIDLE);
assign WREADY  = (wstate == WRDATA);
assign BRESP   = 2'b00;  // OKAY
assign BVALID  = (wstate == WRRESP);
assign wmask   = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} };
assign aw_hs   = AWVALID & AWREADY;
assign w_hs    = WVALID & WREADY;

// wstate
always @(posedge ACLK) begin
    if (~ARESETN)
        wstate <= WRIDLE;
    else
        wstate <= wnext;
end

// wnext
always @(*) begin
    case (wstate)
        WRIDLE:
            if (AWVALID)
                wnext = WRDATA;
            else
                wnext = WRIDLE;
        WRDATA:
            if (WVALID)
                wnext = WRRESP;
            else
                wnext = WRDATA;
        WRRESP:
            if (BREADY)
                wnext = WRIDLE;
            else
                wnext = WRRESP;
        default:
            wnext = WRIDLE;
    endcase
end

// waddr
always @(posedge ACLK) begin
    if (aw_hs)
        waddr <= AWADDR[ADDR_BITS-1:0];
end
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

//++++++++++++++++++++++++axi read+++++++++++++++++++++++
assign ARREADY = (rstate == RDIDLE);
assign RDATA   = rdata;
assign RRESP   = 2'b00;  // OKAY
assign RVALID  = (rstate == RDDATA);
assign ar_hs   = ARVALID & ARREADY;
assign raddr   = ARADDR[ADDR_BITS-1:0];

// rstate
always @(posedge ACLK) begin
    if (~ARESETN)
        rstate <= RDIDLE;
    else
        rstate <= rnext;
end

// rnext
always @(*) begin
    case (rstate)
        RDIDLE:
            if (ARVALID)
                rnext = RDDATA;
            else
                rnext = RDIDLE;
        RDDATA:
            if (RREADY)
                rnext = RDIDLE;
            else
                rnext = RDDATA;
        default:
            rnext = RDIDLE;
    endcase
end

// rdata
always @(posedge ACLK) begin
    if (ar_hs) begin
        rdata <= 1'b0;
        case (raddr)
            ADDR_AP_CTRL: begin
                rdata[0] <= ap_start;
                rdata[1] <= ap_done;
                rdata[2] <= ap_idle;
                rdata[3] <= ap_ready;
                rdata[7] <= auto_restart;
            end
            ADDR_GIE: begin
                rdata <= gie;
            end
            ADDR_IER: begin
                rdata <= ier;
            end
            ADDR_ISR: begin
                rdata <= isr;
            end
            ADDR_CAM_ADDR_CTRL: begin
                rdata[0] <= _cam_addr_ap_vld;
                rdata[1] <= _cam_addr_ap_ack;
            end
            ADDR_CAM_ADDR_DATA_0: begin
                rdata <= _cam_addr[31:0];
            end
            ADDR_LAP_ADDR_CTRL: begin
                rdata[0] <= _lap_addr_ap_vld;
            end
            ADDR_LAP_ADDR_DATA_0: begin
                rdata <= _lap_addr[31:0];
            end
            ADDR_AP_RETURN_0: begin
                rdata <= ap_return[31:0];
            end
        endcase
    end
end
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

//++++++++++++++++++++++++internal registers+++++++++++++
assign interrupt         = gie & (|isr);
assign I_ap_start        = ap_start;
assign ap_idle           = O_ap_idle;
assign ap_ready          = O_ap_ready;
assign I_cam_addr_ap_vld = _cam_addr_ap_vld;
assign _cam_addr_ap_ack  = I_cam_addr_ap_ack;
assign I_cam_addr        = _cam_addr;
assign I_lap_addr_ap_vld = _lap_addr_ap_vld;
assign I_lap_addr        = _lap_addr;
assign ap_return         = O_ap_return;

// ap_start
always @(posedge ACLK) begin
    if (~ARESETN)
        ap_start <= 1'b0;
    else if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0] && WDATA[0])
        ap_start <= 1'b1;
    else if (O_ap_ready)
        ap_start <= auto_restart; // clear on handshake/auto restart
end

// ap_done
always @(posedge ACLK) begin
    if (~ARESETN)
        ap_done <= 1'b0;
    else if (O_ap_done)
        ap_done <= 1'b1;
    else if (ar_hs && raddr == ADDR_AP_CTRL)
        ap_done <= 1'b0; // clear on read
end

// auto_restart
always @(posedge ACLK) begin
    if (~ARESETN)
        auto_restart <= 1'b0;
    else if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0])
        auto_restart <=  WDATA[7];
end

// gie
always @(posedge ACLK) begin
    if (~ARESETN)
        gie <= 1'b0;
    else if (w_hs && waddr == ADDR_GIE && WSTRB[0])
        gie <= WDATA[0];
end

// ier
always @(posedge ACLK) begin
    if (~ARESETN)
        ier <= 1'b0;
    else if (w_hs && waddr == ADDR_IER && WSTRB[0])
        ier <= WDATA[1:0];
end

// isr[0]
always @(posedge ACLK) begin
    if (~ARESETN)
        isr[0] <= 1'b0;
    else if (ier[0] & O_ap_done)
        isr[0] <= 1'b1;
    else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
        isr[0] <= isr[0] ^ WDATA[0]; // toggle on write
end

// isr[1]
always @(posedge ACLK) begin
    if (~ARESETN)
        isr[1] <= 1'b0;
    else if (ier[1] & O_ap_ready)
        isr[1] <= 1'b1;
    else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
        isr[1] <= isr[1] ^ WDATA[1]; // toggle on write
end

// _cam_addr_ap_vld
always @(posedge ACLK) begin
    if (~ARESETN)
        _cam_addr_ap_vld <= 1'b0;
    else if (w_hs && waddr == ADDR_CAM_ADDR_CTRL && WSTRB[0] && WDATA[0])
        _cam_addr_ap_vld <= 1'b1;
    else if (I_cam_addr_ap_ack)
        _cam_addr_ap_vld <= 1'b0; // clear on handshake
end

// _cam_addr[31:0]
always @(posedge ACLK) begin
    if (w_hs && waddr == ADDR_CAM_ADDR_DATA_0)
        _cam_addr[31:0] <= (WDATA[31:0] & wmask) | (_cam_addr[31:0] & ~wmask);
end

// _lap_addr_ap_vld
always @(posedge ACLK) begin
    if (~ARESETN)
        _lap_addr_ap_vld <= 1'b0;
    else if (w_hs && waddr == ADDR_LAP_ADDR_CTRL && WSTRB[0] && WDATA[0])
        _lap_addr_ap_vld <= 1'b1;
    else
        _lap_addr_ap_vld <= 1'b0; // self clear
end

// _lap_addr[31:0]
always @(posedge ACLK) begin
    if (w_hs && waddr == ADDR_LAP_ADDR_DATA_0)
        _lap_addr[31:0] <= (WDATA[31:0] & wmask) | (_lap_addr[31:0] & ~wmask);
end

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++

endmodule


  1. 2013年11月28日 04:53 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP5(lap_filter_axim.v のHDLソース)

AXI4 Master アクセスのラプラシアン・フィルタ IP4(シミュレーション2)”の続き。

現在のところの lap_filter_axim.v を貼っておく。この回路の動作を下に示す。

1.画像データのDDR3メモリのアドレスと、ラプラシアン・フィルタ後の画像データのDDR3メモリのアドレスを内部レジスタに AXI4 Lite Slave アクセスでARMプロセッサからレジスタにWriteしてもらう。この行為に依って、ラプラシアン・フィルタ回路が動作する。
2.DDR3 メモリから画像データを1ライン分、AXI4 Master Read Transaction でRead する。
3.ラプラシアン・フィルタを掛けた後に、異なるDDR3 メモリのアドレスに、AXI4 Master Write Transaction でフィルタ後の1ライン分の画像データをWriteする。
3.2.から3.を1フレーム分行う。
4.レジスタのap_done ビットをセットする。


下に、lap_filter_axim.v を示す。(2013/12/02:修正)

`default_nettype none

//
// lap_filter_axim.v
// 2013/11/13 by marsee
//


module lap_filter_axim #(/*autoport*/
    // AXI4 Lite Slave Interface
    parameter integer C_S_AXI_LITE_ADDR_WIDTH       = 9,
    parameter integer C_S_AXI_LITE_DATA_WIDTH       = 32,

    // AXI Master Interface
    parameter integer C_INTERCONNECT_M_AXI_WRITE_ISSUING = 8,
    parameter integer C_M_AXI_THREAD_ID_WIDTH       = 1,
    parameter integer C_M_AXI_ADDR_WIDTH            = 32,
    parameter integer C_M_AXI_DATA_WIDTH            = 32,
    parameter integer C_M_AXI_AWUSER_WIDTH          = 1,
    parameter integer C_M_AXI_ARUSER_WIDTH          = 1,
    parameter integer C_M_AXI_WUSER_WIDTH           = 1,
    parameter integer C_M_AXI_RUSER_WIDTH           = 1,
    parameter integer C_M_AXI_BUSER_WIDTH           = 1,
    parameter [31:0]  C_M_AXI_TARGET                = 32'h00000000,
    parameter integer C_M_AXI_BURST_LEN             = 256,
    parameter integer C_OFFSET_WIDTH                = 32,

    /* Disabling these parameters will remove any throttling.
    The resulting ERROR flag will not be useful */
    parameter integer C_M_AXI_SUPPORTS_WRITE         = 1,
    parameter integer C_M_AXI_SUPPORTS_READ          = 1,

    parameter integer HORIZONTAL_PIXELS             = 800,
    parameter integer VERTICAL_LINES                = 600
)
(
    // Clocks and Reset
    input wire                                      s_axi_lite_aclk,
    input wire                                      M_AXI_ACLK,
    input wire                                      ARESETN,

    ///////////////////////////////
    // AXI4 Lite Slave Interface //
    ///////////////////////////////
    // AXI Lite Write Address Channel
    input   wire                                    s_axi_lite_awvalid,
    output  wire                                    s_axi_lite_awready,
    input   wire    [C_S_AXI_LITE_ADDR_WIDTH-1:0]   s_axi_lite_awaddr,

    // AXI Lite Write Data Channel
    input   wire                                    s_axi_lite_wvalid,
    output  wire                                    s_axi_lite_wready,
    input   wire    [C_S_AXI_LITE_DATA_WIDTH-1:0]   s_axi_lite_wdata,
    input   wire    [C_S_AXI_LITE_DATA_WIDTH/8-1:0] s_axi_lite_wstrb,

    // AXI Lite Write Response Channel
    output  wire    [1:0]                           s_axi_lite_bresp,
    output  wire                                    s_axi_lite_bvalid,
    input   wire                                    s_axi_lite_bready,

    // AXI Lite Read Address Channel
    input   wire                                    s_axi_lite_arvalid,
    output  wire                                    s_axi_lite_arready,
    input   wire    [C_S_AXI_LITE_ADDR_WIDTH-1:0]   s_axi_lite_araddr,

    // AXI Lite Read Data Channel
    output  wire                                    s_axi_lite_rvalid,
    input   wire                                    s_axi_lite_rready,
    output  wire    [C_S_AXI_LITE_DATA_WIDTH-1:0]   s_axi_lite_rdata,
    output  wire    [1:0]                           s_axi_lite_rresp,

    ///////////////////////////////
    // AXI4 Master Interface //
    ///////////////////////////////
    // Master Interface Write Address
    output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]       M_AXI_AWID,
    output wire [C_M_AXI_ADDR_WIDTH-1:0]            M_AXI_AWADDR,
    output wire [8-1:0]                             M_AXI_AWLEN,
    output wire [3-1:0]                             M_AXI_AWSIZE,
    output wire [2-1:0]                             M_AXI_AWBURST,
    output wire                  M_AXI_AWLOCK,
    output wire [4-1:0]                             M_AXI_AWCACHE,
    output wire [3-1:0]                             M_AXI_AWPROT,
    // AXI3 output wire [4-1:0]                  M_AXI_AWREGION,
    output wire [4-1:0]                             M_AXI_AWQOS,
    output wire [C_M_AXI_AWUSER_WIDTH-1:0]          M_AXI_AWUSER,
    output wire                                     M_AXI_AWVALID,
    input  wire                                     M_AXI_AWREADY,

    // Master Interface Write Data
    // AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_WID,
    output wire [C_M_AXI_DATA_WIDTH-1:0]            M_AXI_WDATA,
    output wire [C_M_AXI_DATA_WIDTH/8-1:0]          M_AXI_WSTRB,
    output wire                                     M_AXI_WLAST,
    output wire [C_M_AXI_WUSER_WIDTH-1:0]           M_AXI_WUSER,
    output wire                                     M_AXI_WVALID,
    input  wire                                     M_AXI_WREADY,

    // Master Interface Write Response
    input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]       M_AXI_BID,
    input  wire [2-1:0]                             M_AXI_BRESP,
    input  wire [C_M_AXI_BUSER_WIDTH-1:0]           M_AXI_BUSER,
    input  wire                                     M_AXI_BVALID,
    output wire                                     M_AXI_BREADY,

    // Master Interface Read Address
    output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]       M_AXI_ARID,
    output wire [C_M_AXI_ADDR_WIDTH-1:0]            M_AXI_ARADDR,
    output wire [8-1:0]                             M_AXI_ARLEN,
    output wire [3-1:0]                             M_AXI_ARSIZE,
    output wire [2-1:0]                             M_AXI_ARBURST,
    output wire [2-1:0]                             M_AXI_ARLOCK,
    output wire [4-1:0]                             M_AXI_ARCACHE,
    output wire [3-1:0]                             M_AXI_ARPROT,
    // AXI3 output wire [4-1:0]          M_AXI_ARREGION,
    output wire [4-1:0]                             M_AXI_ARQOS,
    output wire [C_M_AXI_ARUSER_WIDTH-1:0]          M_AXI_ARUSER,
    output wire                                     M_AXI_ARVALID,
    input  wire                                     M_AXI_ARREADY,

    // Master Interface Read Data
    input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]       M_AXI_RID,
    input  wire [C_M_AXI_DATA_WIDTH-1:0]            M_AXI_RDATA,
    input  wire [2-1:0]                             M_AXI_RRESP,
    input  wire                                     M_AXI_RLAST,
    input  wire [C_M_AXI_RUSER_WIDTH-1:0]           M_AXI_RUSER,
    input  wire                                     M_AXI_RVALID,
    output wire                                     M_AXI_RREADY,

    // User Signals
    output  wire                                    interrupt,

    // Error Signal
    output  reg                                     write_fifo_overflow
);

    // Beyond Circuts, Constant Function in Verilog 2001
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction

    wire [31:0]               I_cam_addr;
    wire                      I_cam_addr_ap_vld;
    reg                       I_cam_addr_ap_ack;
    wire [31:0]               I_lap_addr;
    wire                      I_lap_addr_ap_vld;
    wire                      I_ap_start;
    wire                      O_ap_ready;
    wire                      O_ap_done;
    wire                      O_ap_idle;
    wire [31:0]               O_ap_return;
    reg     lap_addr_ap_vld_hold;

    reg write_adfifo_wr_ena;
    reg [C_M_AXI_ADDR_WIDTH-1:0] write_adfifo_addr;
    reg [7:0] write_adfifo_awlen;
    reg write_fifo_wr_ena;
    wire [31:0] write_fifo_write_data;
    wire [3:0] write_fifo_wstrb;
    wire read_adfifo_wr_ena;
    wire [31:0] read_adfifo_addr;
    wire [7:0] read_adfifo_arlen;
    wire read_fifo_rd_ena;
    reg init_done;
    wire write_adfifo_full;
    wire write_fifo_full;
    wire write_fifo_almost_full;
    wire read_adfifo_full;
    wire [31:0] read_fifo_read_data;
    wire read_fifo_empty_n;
    wire read_fifo_almost_empty_n;
    wire wr_resp_err;

    parameter [2:0] IDLE_MAIN =                     3'b000,
                    LINE_READ_AND_Y_1ST =           3'b001,
                    LINE_READ_AND_Y_2ND =           3'b011,
                    LINE_READ_AND_Y =               3'b010,
                    LAP_FILTER_AND_WRITE =          3'b110,
                    WAIT_AXI_WRITE_TRANSACTION =    3'b111,
                    AP_DONE_ACTIVE =                3'b101;
    reg     [2:0]   main_cs;

    parameter [1:0] IDLE_LINE_READ_AND_Y =      2'b00,
                    LINE_READ_AND_Y_START =     2'b01,
                    LINE_READ_AND_Y_ACTIVE =    2'b11;
    reg     [1:0]   line_read_y_cs;
    reg             line_read_y_start;
    reg     [C_M_AXI_ADDR_WIDTH-1:0]  start_addr;
    wire    line_read_y_done;
    wire    [7:0]   y_data;
    wire            y_data_valid;
    reg     [1:0]   line_buffer_wcount, line_buffer_rcount;
    wire            line_buf0_we, line_buf1_we, line_buf2_we;
    wire    [7:0]   line_buf_dout0, line_buf_dout1, line_buf_dout2;
    reg     [9:0]  line_buf_waddr, line_buf_raddr;
    reg     [7:0]   Xp1Ym1, Xp1Yn, Xp1Yp1;
    reg     [7:0]   XnYm1, XnYn, XnYp1, Xm1Ym1, Xm1Yn, Xm1Yp1;
    reg     [7:0]   lap_filter_out;
    reg     [log2(HORIZONTAL_PIXELS)-1:0]   lap_pixel_count;
    reg     [log2(VERTICAL_LINES)-1:0]      lap_line_count;

    parameter       IDLE_WRITE_ADDR =   1'b0,
                    WRITE_ADDR_ISSUE =  1'b1;
    reg             write_addr_cs;
    reg     [log2(HORIZONTAL_PIXELS)-1:0]   write_addr_count;
    wire            ACLK;
    wire            lap_line_end;
    wire            lap_frame_end;
    wire            write_fifo_empty;


    assign ACLK = M_AXI_ACLK;

    // AXI4 Lite Slave Module
    lap_filter_axim_LiteS_if #(
        .C_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
        .C_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH)
    ) lap_filter_axim_LiteS_if_U(
        .ACLK(s_axi_lite_aclk),
        .ARESETN(ARESETN),
        .AWADDR(s_axi_lite_awaddr),
        .AWVALID(s_axi_lite_awvalid),
        .AWREADY(s_axi_lite_awready),
        .WDATA(s_axi_lite_wdata),
        .WSTRB(s_axi_lite_wstrb),
        .WVALID(s_axi_lite_wvalid),
        .WREADY(s_axi_lite_wready),
        .BRESP(s_axi_lite_bresp),
        .BVALID(s_axi_lite_bvalid),
        .BREADY(s_axi_lite_bready),
        .ARADDR(s_axi_lite_araddr),
        .ARVALID(s_axi_lite_arvalid),
        .ARREADY(s_axi_lite_arready),
        .RDATA(s_axi_lite_rdata),
        .RRESP(s_axi_lite_rresp),
        .RVALID(s_axi_lite_rvalid),
        .RREADY(s_axi_lite_rready),
        .interrupt(interrupt),
        .I_cam_addr(I_cam_addr),
        .I_cam_addr_ap_vld(I_cam_addr_ap_vld),
        .I_cam_addr_ap_ack(I_cam_addr_ap_ack),
        .I_lap_addr(I_lap_addr),
        .I_lap_addr_ap_vld(I_lap_addr_ap_vld),
        .I_ap_start(I_ap_start),
        .O_ap_ready(O_ap_ready),
        .O_ap_done(O_ap_done),
        .O_ap_idle(O_ap_idle),
        .O_ap_return(O_ap_return)
    );

    // I_lap_addr_ap_vld
    always @(posedge ACLK) begin : proc_lap_addr_ap_valid_hold
       if(~ARESETN) begin
            lap_addr_ap_vld_hold <= 1'b0;
       end else begin
            if (I_lap_addr_ap_vld)
                lap_addr_ap_vld_hold <= 1'b1;
       end
    end

    // cam_addr_ap_vld, lap_addr_ap_vld  init_done
    always @(posedge s_axi_lite_aclk) begin : proc_init_done
       if(~ARESETN) begin
            init_done <= 1'b0;
            I_cam_addr_ap_ack <= 1'b0;
       end else begin
            if (lap_addr_ap_vld_hold & I_cam_addr_ap_vld) begin
                init_done <= 1'b1;
                I_cam_addr_ap_ack <= 1'b1;
            end
       end
    end

    assign O_ap_return = 32'd1;

    // axi4_master_inf instance
    axi4_master_inf #(
        .C_M_AXI_DATA_WIDTH(32)
    ) axi4_master_inf_U (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .M_AXI_AWID(M_AXI_AWID),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWLEN(M_AXI_AWLEN),
        .M_AXI_AWSIZE(M_AXI_AWSIZE),
        .M_AXI_AWBURST(M_AXI_AWBURST),
        .M_AXI_AWLOCK(M_AXI_AWLOCK),
        .M_AXI_AWCACHE(M_AXI_AWCACHE),
        .M_AXI_AWPROT(M_AXI_AWPROT),
        .M_AXI_AWQOS(M_AXI_AWQOS),
        .M_AXI_AWUSER(M_AXI_AWUSER),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WLAST(M_AXI_WLAST),
        .M_AXI_WUSER(M_AXI_WUSER),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BID(M_AXI_BID),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BUSER(M_AXI_BUSER),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .M_AXI_ARID(M_AXI_ARID),
        .M_AXI_ARADDR(M_AXI_ARADDR),
        .M_AXI_ARLEN(M_AXI_ARLEN),
        .M_AXI_ARSIZE(M_AXI_ARSIZE),
        .M_AXI_ARBURST(M_AXI_ARBURST),
        .M_AXI_ARLOCK(M_AXI_ARLOCK),
        .M_AXI_ARCACHE(M_AXI_ARCACHE),
        .M_AXI_ARPROT(M_AXI_ARPROT),
        .M_AXI_ARQOS(M_AXI_ARQOS),
        .M_AXI_ARUSER(M_AXI_ARUSER),
        .M_AXI_ARVALID(M_AXI_ARVALID),
        .M_AXI_ARREADY(M_AXI_ARREADY),
        .M_AXI_RID(M_AXI_RID),
        .M_AXI_RDATA(M_AXI_RDATA),
        .M_AXI_RRESP(M_AXI_RRESP),
        .M_AXI_RLAST(M_AXI_RLAST),
        .M_AXI_RUSER(M_AXI_RUSER),
        .M_AXI_RVALID(M_AXI_RVALID),
        .M_AXI_RREADY(M_AXI_RREADY),
        .write_clk(ACLK),
        .write_rst(~ARESETN),
        .write_adfifo_wr_ena(write_adfifo_wr_ena),
        .write_adfifo_addr(write_adfifo_addr),
        .write_adfifo_awlen(write_adfifo_awlen),
        .write_adfifo_full(write_adfifo_full),
        .write_fifo_wr_ena(write_fifo_wr_ena),
        .write_fifo_write_data(write_fifo_write_data),
        .write_fifo_wstrb(write_fifo_wstrb),
        .write_fifo_full(write_fifo_full),
        .write_fifo_almost_full(write_fifo_almost_full),
        .write_fifo_empty(write_fifo_empty),
        .read_clk(ACLK),
        .read_rst(~ARESETN),
        .read_adfifo_wr_ena(read_adfifo_wr_ena),
        .read_adfifo_addr(read_adfifo_addr),
        .read_adfifo_arlen(read_adfifo_arlen),
        .read_adfifo_full(read_adfifo_full),
        .read_fifo_rd_ena(read_fifo_rd_ena),
        .read_fifo_read_data(read_fifo_read_data),
        .read_fifo_empty_n(read_fifo_empty_n),
        .read_fifo_almost_empty_n(read_fifo_almost_empty_n),
        .wr_resp_err(wr_resp_err),
        .init_done(init_done)
    );

    // write_fifo_overflow
    always @(posedge ACLK) begin : proc_write_fifo_overflow
       if(~ARESETN) begin
            write_fifo_overflow <= 1'b0;
       end else begin
            if (write_fifo_full & write_adfifo_wr_ena)
                write_fifo_overflow <= 1'b1;
       end
    end

    // Main State Machine
    always @(posedge ACLK) begin : proc_main_sm
       if(~ARESETN) begin
            main_cs <= IDLE_MAIN;
       end else begin
            case (main_cs)
                IDLE_MAIN :
                    if (init_done & I_ap_start) begin
                        main_cs <= LINE_READ_AND_Y_1ST;
                    end
                LINE_READ_AND_Y_1ST :
                    if (line_read_y_done) begin
                        main_cs <= LINE_READ_AND_Y;
                    end
                LINE_READ_AND_Y :
                    if (line_read_y_done) begin
                        main_cs <= LAP_FILTER_AND_WRITE;
                    end
                LAP_FILTER_AND_WRITE :
                    if (lap_frame_end) begin
                        main_cs <= AP_DONE_ACTIVE;
                    end else if (lap_line_end) begin
                        main_cs <= WAIT_AXI_WRITE_TRANSACTION;
                    end
                WAIT_AXI_WRITE_TRANSACTION :    // Write Transaction が完了するまでWait
                    if (write_fifo_empty)
                         main_cs <= LINE_READ_AND_Y;
                AP_DONE_ACTIVE : begin
                    main_cs <= IDLE_MAIN;
                end

               default : /* default */;
            endcase
       end
    end

    assign O_ap_done = (main_cs==AP_DONE_ACTIVE) ? 1'b1 : 1'b0;
    assign O_ap_ready = (main_cs==AP_DONE_ACTIVE) ? 1'b1 : 1'b0;
    assign O_ap_idle = (main_cs==IDLE_MAIN) ? 1'b1 : 1'b0;

    // 1 line Read State Machine
    always @(posedge ACLK) begin : proc_line_read_and_y_SM
       if(~ARESETN) begin
            line_read_y_cs <= IDLE_LINE_READ_AND_Y;
            line_read_y_start <= 1'b0;
       end else begin
            case (line_read_y_cs)
                IDLE_LINE_READ_AND_Y :
                    if (main_cs==LINE_READ_AND_Y_1ST || main_cs==LINE_READ_AND_Y_2ND || main_cs==LINE_READ_AND_Y) begin
                        line_read_y_cs <= LINE_READ_AND_Y_START;
                        line_read_y_start <= 1'b1;
                    end
                LINE_READ_AND_Y_START : begin
                    line_read_y_cs <= LINE_READ_AND_Y_ACTIVE;
                    line_read_y_start <= 1'b0;
                end
                LINE_READ_AND_Y_ACTIVE :
                    if (line_read_y_done)
                        line_read_y_cs <= IDLE_LINE_READ_AND_Y;
               default : /* default */;
            endcase
       end
    end

    line_read_and_y #(
        .C_M_AXI_ADDR_WIDTH(32),
        .C_M_AXI_DATA_WIDTH(32),
        .HORIZONTAL_PIXELS(800)
    ) line_read_and_y_U (/*autoinst*/
        .clk(ACLK),
        .reset(~ARESETN),
        .start_addr(start_addr[C_M_AXI_ADDR_WIDTH-1:0]),
        .start(line_read_y_start),
        .done(line_read_y_done),
        .y_data(y_data[7:0]),
        .y_data_valid(y_data_valid),
        .read_adfifo_wr_ena(read_adfifo_wr_ena),
        .read_adfifo_addr(read_adfifo_addr[C_M_AXI_ADDR_WIDTH-1:0]),
        .read_adfifo_arlen(read_adfifo_arlen[8-1:0]),
        .read_fifo_rd_ena(read_fifo_rd_ena),
        .read_adfifo_full(read_adfifo_full),
        .read_fifo_read_data(read_fifo_read_data[C_M_AXI_DATA_WIDTH-1:0]),
        .read_fifo_empty_n(read_fifo_empty_n),
        .read_fifo_almost_empty_n(read_fifo_almost_empty_n)
    );

    // line_read_and_y の start_addr の処理
    always @(posedge ACLK) begin : proc_start_addr
       if(~ARESETN) begin
            start_addr <= 0;
       end else begin
            if (I_cam_addr_ap_vld)
                start_addr <= I_cam_addr;
            else if (line_read_y_start) begin
                start_addr <= start_addr + HORIZONTAL_PIXELS*(C_M_AXI_DATA_WIDTH/8);
            end
       end
    end

    // line buffer として使用するDual Port Memory を決定する
    always @(posedge ACLK) begin : proc_line_buffer_wcount
       if(~ARESETN) begin
            line_buffer_wcount <= 2'd0;
       end else begin
            if (line_read_y_done) begin
                if (line_buffer_wcount == 2'd2)
                    line_buffer_wcount <= 2'd0;
                else
                    line_buffer_wcount <= line_buffer_wcount + 2'd1;
            end
       end
    end

    assign line_buf0_we = (line_buffer_wcount==2'd0 && y_data_valid==1'b1) ? 1'b1 : 1'b0;
    assign line_buf1_we = (line_buffer_wcount==2'd1 && y_data_valid==1'b1) ? 1'b1 : 1'b0;
    assign line_buf2_we = (line_buffer_wcount==2'd2 && y_data_valid==1'b1) ? 1'b1 : 1'b0;

    // line buffer 0
    Dual_Port_Memory #(
        .C_MEMORY_SIZE(1024),
        .DATA_BUS_WIDTH(8)
    ) line_buffer_0 (/*autoinst*/
            .dout(line_buf_dout0),
            .clk(ACLK),
            .we(line_buf0_we),
            .waddr(line_buf_waddr),
            .raddr(line_buf_raddr),
            .din(y_data)
     );
        // line buffer 1
    Dual_Port_Memory #(
        .C_MEMORY_SIZE(1024),
        .DATA_BUS_WIDTH(8)
    ) line_buffer_1 (/*autoinst*/
            .dout(line_buf_dout1),
            .clk(ACLK),
            .we(line_buf1_we),
            .waddr(line_buf_waddr),
            .raddr(line_buf_raddr),
            .din(y_data)
     );
        // line buffer 2
    Dual_Port_Memory #(
        .C_MEMORY_SIZE(1024),
        .DATA_BUS_WIDTH(8)
    ) line_buffer_2 (/*autoinst*/
            .dout(line_buf_dout2),
            .clk(ACLK),
            .we(line_buf2_we),
            .waddr(line_buf_waddr),
            .raddr(line_buf_raddr),
            .din(y_data)
     );

    // line_buf_waddr
    always @(posedge ACLK) begin : proc_line_buf_waddr
       if(~ARESETN) begin
            line_buf_waddr <= 10'd0;
       end else begin
            if (line_read_y_start)
                line_buf_waddr <= 10'd0;
            else if (y_data_valid)
                line_buf_waddr <= line_buf_waddr + 10'd1;
       end
    end

    // line_buf_raddr
    always @(posedge ACLK) begin : proc_line_buf_raddr
       if(~ARESETN) begin
            line_buf_raddr <= 10'd0;
       end else begin
            if (main_cs == LAP_FILTER_AND_WRITE)
                line_buf_raddr <= line_buf_raddr + 10'd1;
            else
                line_buf_raddr <= 10'd0;
       end
    end

    // line_buffer_rcount
    always @(posedge ACLK) begin : proc_line_buffer_rcount
       if(~ARESETN) begin
            line_buffer_rcount <= 2'd0;
       end else begin
            if (lap_line_end) begin
                if (line_buffer_rcount==2'd2)
                    line_buffer_rcount <= 2'd0;
                else
                    line_buffer_rcount <= line_buffer_rcount + 2'd1;
            end
       end
    end

    // Xp1Ym1, Xp1Yn, Xp1Yp1
    // 最初のラインは3ライン揃っていない状態でオール0の値を出力するので、3ライン揃うのはline_buffer_rcount==1の時からなので、1つずれている
    always @(posedge ACLK) begin : proc_XY_first_input
       if(~ARESETN) begin
            Xp1Ym1  <=  8'd0;
            Xp1Yn   <=  8'd0;
            Xp1Yp1  <=  8'd0;
       end else begin
            if (main_cs == LAP_FILTER_AND_WRITE) begin
                case (line_buffer_rcount)
                    2'd0 : begin
                        Xp1Ym1  <=  line_buf_dout2;
                        Xp1Yn   <=  line_buf_dout0;
                        Xp1Yp1  <=  line_buf_dout1;
                    end
                    2'd1 : begin
                        Xp1Ym1  <=  line_buf_dout0;
                        Xp1Yn   <=  line_buf_dout1;
                        Xp1Yp1  <=  line_buf_dout2;
                    end
                    2'd2 : begin
                        Xp1Ym1  <=  line_buf_dout1;
                        Xp1Yn   <=  line_buf_dout2;
                        Xp1Yp1  <=  line_buf_dout0;
                    end
                    default : /* default */;
                endcase
            end
       end
    end

    // XnYm1, XnYn, XnYp1, Xm1Ym1, Xm1Yn, Xm1Yp1
    always @(posedge ACLK) begin : proc_XY_2_3_stage
       if(~ARESETN) begin
            XnYm1   <=  8'd0;
            XnYn    <=  8'd0;
            XnYp1   <=  8'd0;
            Xm1Ym1  <=  8'd0;
            Xm1Yn   <=  8'd0;
            Xm1Yp1  <=  8'd0;
       end else begin
            XnYm1   <=  Xp1Ym1;
            XnYn    <=  Xp1Yn;
            XnYp1   <=  Xp1Yp1;
            Xm1Ym1  <=  XnYm1;
            Xm1Yn   <=  XnYn;
            Xm1Yp1  <=  XnYp1;
       end
    end

    // laplacian filter
    // DPMで1クロック、ラプラシアン・フィルタ用FFで3クロック遅延している
    always @(posedge ACLK) begin : proc_laplacian_filter
        reg    [12:0]  laplacian_filter;

       if(~ARESETN) begin
            lap_filter_out <= 8'd0;
       end else begin
            laplacian_filter = {1'b0, XnYn, 3'b000} - {4'b0000, Xp1Ym1} - {4'b0000, Xp1Yn} - {4'b0000, Xp1Yp1} - {4'b0000, XnYm1} - {4'b0000, XnYm1} - {4'b0000, Xm1Ym1} - {4'b0000, Xm1Yn} - {4'b0000, Xm1Yp1};

            // 1line のうちの最初と最後は0
            // DPMで1クロック、ラプラシアン・フィルタ用FFで3クロック遅延している。つまりデータが出てくるのは、lap_pixel_count=4 の時
            if (main_cs==LAP_FILTER_AND_WRITE && lap_pixel_count>=4 && lap_pixel_count<HORIZONTAL_PIXELS+2 && lap_line_count>=1 && lap_line_count<VERTICAL_LINES-1) begin
                if (laplacian_filter[11])   // minus
                    lap_filter_out <= 8'd0;
                else if (laplacian_filter[10]==1'b1 || laplacian_filter[9]==1'b1 || laplacian_filter[8]==1'b1)
                    lap_filter_out <= 8'd255;
                else
                    lap_filter_out <= laplacian_filter[7:0];
            end else
                lap_filter_out <= 8'd0;
       end
    end
    assign write_fifo_write_data = {8'b0000_0000, lap_filter_out, lap_filter_out, lap_filter_out};  // 8'd0, R, G, B
    assign write_fifo_wstrb = 4'b1111;

    // lap_pixel_count
    // ラプラシアン/フィルタの1 line = lap_pixel_count>=3 && lap_pixel_count<HORIZONTAL_PIXELS+3
    always @(posedge ACLK) begin : proc_lap_pixel_count
       if(~ARESETN) begin
            lap_pixel_count <= 0;
       end else begin
            if (main_cs==LAP_FILTER_AND_WRITE) begin
                if (lap_pixel_count == HORIZONTAL_PIXELS+2)
                    lap_pixel_count <= 0;
                else
                    lap_pixel_count <= lap_pixel_count + 1;
            end else
                lap_pixel_count <= 0;
       end
    end
    assign lap_line_end = (lap_pixel_count==HORIZONTAL_PIXELS+2) ? 1'b1 : 1'b0;

    // lap_line_count
    always @(posedge ACLK) begin : proc_lap_line_count
       if(~ARESETN) begin
            lap_line_count <= 0;
       end else begin
            if (main_cs==LAP_FILTER_AND_WRITE) begin
                if (lap_pixel_count==HORIZONTAL_PIXELS+2) begin
                    if (lap_line_count==VERTICAL_LINES-1)
                                lap_line_count <= 0;
                    else
                        lap_line_count <= lap_line_count + 1;
                end
            end
       end
    end
    assign lap_frame_end = (lap_pixel_count==HORIZONTAL_PIXELS+2 && lap_line_count==VERTICAL_LINES-1) ? 1'b1 : 1'b0;

    // wirte_fifo_wr_ena
    // ラプラシアン/フィルタの1 line = lap_pixel_count>=3 && lap_pixel_count<HORIZONTAL_PIXELS+3
    // write_adfifo_wr_ena の enable は、1クロック早く、ap_pixel_count==2 でenableし、ap_pixel_count==HORIZONTAL_PIXELS+2でディスエーブル
    always @(posedge ACLK) begin : proc_wirte_fifo_wr_ena
       if(~ARESETN) begin
            write_fifo_wr_ena <= 1'b0;
       end else begin
            if (write_fifo_almost_full)
                write_fifo_wr_ena <= 1'b0;
            else if (lap_pixel_count==2)
                write_fifo_wr_ena <= 1'b1;
            else if (lap_pixel_count==HORIZONTAL_PIXELS+2)
                write_fifo_wr_ena <= 1'b0;
       end
    end

    // write_adfifo_wr_ena, write_adfifo_wr_ena State Machine
    always @(posedge ACLK) begin : proc_write_addr_SM
       if(~ARESETN) begin
            write_addr_cs <= IDLE_WRITE_ADDR;
            write_adfifo_wr_ena <= 1'b0;
       end else begin
            case (write_addr_cs)
                IDLE_WRITE_ADDR :
                    if (main_cs==LAP_FILTER_AND_WRITE && write_addr_count!=0) begin
                        write_addr_cs <= WRITE_ADDR_ISSUE;
                        write_adfifo_wr_ena <= 1'b1;
                    end
                WRITE_ADDR_ISSUE :
                    begin
                        write_addr_cs <= IDLE_WRITE_ADDR;
                        write_adfifo_wr_ena <= 1'b0;
                    end
               default : /* default */;
            endcase
       end
    end

    // write_addr_count, write_adfifo_awlen
    always @(posedge ACLK) begin : proc_write_addr_count
       if(~ARESETN) begin
            write_addr_count <= HORIZONTAL_PIXELS;
            write_adfifo_awlen <= 8'd255;
       end else begin
            if (write_addr_cs==IDLE_WRITE_ADDR && main_cs==LAP_FILTER_AND_WRITE && write_addr_count!=0) begin
                if (write_addr_count >= 256) begin
                    write_addr_count <= write_addr_count - 10'd256;
                    write_adfifo_awlen <= 8'd255;
                end else begin // less than 256
                    write_addr_count <= 10'd0;
                    write_adfifo_awlen <= write_addr_count[7:0]-8'd1;
                end
            end else if (main_cs == LINE_READ_AND_Y)
                write_addr_count <= HORIZONTAL_PIXELS;
       end
    end

    // write_adfifo_addr
    always @(posedge ACLK) begin : proc_write_addr
       if(~ARESETN) begin
            write_adfifo_addr <= I_lap_addr;
       end else begin
            if (I_lap_addr_ap_vld)
                write_adfifo_addr <= I_lap_addr;
            else if (write_adfifo_wr_ena)
                write_adfifo_addr <= write_adfifo_addr + (write_adfifo_awlen + 8'd1)*(C_M_AXI_DATA_WIDTH/8);
       end
    end

endmodule

`default_nettype wire

  1. 2013年11月27日 05:21 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP4(シミュレーション2)

AXI4 Master アクセスのラプラシアン・フィルタ IP3(シミュレーション)”の続き。

前回の AXI4 Master アクセスのラプラシアン・フィルタ IP には欠点があった。それは、ラプラシアン・フィルタ結果をDDR3 SDRAMにWrite するときに終了をブロックしていないことだ。もし、AXI4 Write Transaction の終了、次のAXI4 Read Transaction より長く掛かってしまった場合は、write_data FIFOが溢れてしまう危険がある。現在のところwrite_data FIFOがFULLなった時ののデータ停止は行っていない。つまり手抜きです。。。
その代わり、AXI4 Write Transaction の終了までブロックするようにメインのステートマシンを変更した。メインのステートマシンを下に示す。

    // Main State Machine
    always @(posedge ACLK) begin : proc_main_sm
       if(~ARESETN) begin
            main_cs <= IDLE_MAIN;
       end else begin
            case (main_cs)
                IDLE_MAIN :
                    if (init_done & I_ap_start) begin
                        main_cs <= LINE_READ_AND_Y_1ST;
                    end
                LINE_READ_AND_Y_1ST :
                    if (line_read_y_done) begin
                        main_cs <= LINE_READ_AND_Y;
                    end
                LINE_READ_AND_Y :
                    if (line_read_y_done) begin
                        main_cs <= LAP_FILTER_AND_WRITE;
                    end
                LAP_FILTER_AND_WRITE :
                    if (lap_frame_end) begin
                        main_cs <= AP_DONE_ACTIVE;
                    end else if (lap_line_end) begin
                        main_cs <= WAIT_AXI_WRITE_TRANSACTION;
                    end
                WAIT_AXI_WRITE_TRANSACTION :    // Write Transaction が完了するまでWait
                    if (write_fifo_empty)
                         main_cs <= LINE_READ_AND_Y;
                AP_DONE_ACTIVE : begin
                    main_cs <= IDLE_MAIN;
                end

               default : /* default */;
            endcase
       end
    end


WAIT_AXI_WRITE_TRANSACTION ステートが新たに新設したAXI4 Write Transaction の終了までブロックするステートだ。axi_master_inf.v に、write_data FIFO のempty をwrite_clk で同期した write_fifo_empty ポートを増設して、それを見ている。これで write_data が空なのが確認できる。
更に、write_data FIFO の overflow を監視するために、write_fifo_overflow ポートを増やした。これは、write_fifo_full の時に、write_adfifo_wr_ena が来たかどうかを確認している。

下に、AXI4 TransactionのWrite とReadの様子のシミュレーション波形を示す。上の AXI4 Write Transction のデータ・チャネルの長さが、下の AXI4 Read Transaction のデータ・チャネルより長くなっているのが見える。長くなっても、ReadがWriteを待っているのがわかると追う。これは、AXI4 Write データ・チャネルの WREADY をランダムに Waitさせている。これは、AXI4_Slave_BFM の機能だ。
axi4m_lap_filter_14_131126.png

今度は、1フレームのラプラシアン・フィルタに 14.7msec ほどかかっている。全体のシミュレーション波形を示す。write_fifo_overflow はずっと 0 のままである。つまり、FIFOのオーバーフロー・エラーは無い。
axi4m_lap_filter_15_131126.png

因みに、AXI4 Readは、元々ブロックされているので、ブロックする必要はない。これでIPの実装を行うことにする。
下に、テストベンチの lap_filter_axim_tb.v を貼っておく。

`default_nettype none
`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   18:18:43 11/22/2013
// Design Name:   lap_filter_axim
// Module Name:   D:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/Zed_OOB_Design2_HLS/hw/xps_proj/pcores/lap_filter_axim_v1_00_a/lap_filter_axim/lap_filter_axim_tb.v
// Project Name:  lap_filter_axim
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: lap_filter_axim
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module lap_filter_axim_tb;

    parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9; // Address width of the AXI Lite Interface
    parameter integer C_S_AXI_LITE_DATA_WIDTH = 32; // Data width of the AXI Lite Interface

    parameter DELAY = 1;

    // Inputs
    wire s_axi_lite_aclk;
    wire ACLK;
    wire ARESETN;
    reg s_axi_lite_awvalid;
    reg [8:0] s_axi_lite_awaddr;
    reg s_axi_lite_wvalid;
    reg [31:0] s_axi_lite_wdata;
    reg [3:0] s_axi_lite_wstrb;
    reg s_axi_lite_bready;
    reg s_axi_lite_arvalid;
    reg [8:0] s_axi_lite_araddr;
    reg s_axi_lite_rready;
    wire M_AXI_AWREADY;
    wire M_AXI_WREADY;
    wire [0:0] M_AXI_BID;
    wire [1:0] M_AXI_BRESP;
    wire [0:0] M_AXI_BUSER;
    wire M_AXI_BVALID;
    wire M_AXI_ARREADY;
    wire [0:0] M_AXI_RID;
    wire [31:0] M_AXI_RDATA;
    wire [1:0] M_AXI_RRESP;
    wire M_AXI_RLAST;
    wire [0:0] M_AXI_RUSER;
    wire M_AXI_RVALID;

    // Outputs
    wire s_axi_lite_awready;
    wire s_axi_lite_wready;
    wire [1:0] s_axi_lite_bresp;
    wire s_axi_lite_bvalid;
    wire s_axi_lite_arready;
    wire s_axi_lite_rvalid;
    wire [31:0] s_axi_lite_rdata;
    wire [1:0] s_axi_lite_rresp;
    wire [0:0] M_AXI_AWID;
    wire [31:0] M_AXI_AWADDR;
    wire [7:0] M_AXI_AWLEN;
    wire [2:0] M_AXI_AWSIZE;
    wire [1:0] M_AXI_AWBURST;
    wire M_AXI_AWLOCK;
    wire [3:0] M_AXI_AWCACHE;
    wire [2:0] M_AXI_AWPROT;
    wire [3:0] M_AXI_AWQOS;
    wire [0:0] M_AXI_AWUSER;
    wire M_AXI_AWVALID;
    wire [31:0] M_AXI_WDATA;
    wire [3:0] M_AXI_WSTRB;
    wire M_AXI_WLAST;
    wire [0:0] M_AXI_WUSER;
    wire M_AXI_WVALID;
    wire M_AXI_BREADY;
    wire [0:0] M_AXI_ARID;
    wire [31:0] M_AXI_ARADDR;
    wire [7:0] M_AXI_ARLEN;
    wire [2:0] M_AXI_ARSIZE;
    wire [1:0] M_AXI_ARBURST;
    wire [1:0] M_AXI_ARLOCK;
    wire [3:0] M_AXI_ARCACHE;
    wire [2:0] M_AXI_ARPROT;
    wire [3:0] M_AXI_ARQOS;
    wire [0:0] M_AXI_ARUSER;
    wire M_AXI_ARVALID;
    wire M_AXI_RREADY;
    wire interrupt;
    wire write_fifo_overflow;


    // Instantiate the Unit Under Test (UUT)
    lap_filter_axim # (
            .C_S_AXI_LITE_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
            .C_S_AXI_LITE_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH)
        ) uut (
        .s_axi_lite_aclk(s_axi_lite_aclk),
        .M_AXI_ACLK(ACLK),
        .ARESETN(ARESETN),
        .s_axi_lite_awvalid(s_axi_lite_awvalid),
        .s_axi_lite_awready(s_axi_lite_awready),
        .s_axi_lite_awaddr(s_axi_lite_awaddr),
        .s_axi_lite_wvalid(s_axi_lite_wvalid),
        .s_axi_lite_wready(s_axi_lite_wready),
        .s_axi_lite_wdata(s_axi_lite_wdata),
        .s_axi_lite_wstrb(s_axi_lite_wstrb),
        .s_axi_lite_bresp(s_axi_lite_bresp),
        .s_axi_lite_bvalid(s_axi_lite_bvalid),
        .s_axi_lite_bready(s_axi_lite_bready),
        .s_axi_lite_arvalid(s_axi_lite_arvalid),
        .s_axi_lite_arready(s_axi_lite_arready),
        .s_axi_lite_araddr(s_axi_lite_araddr),
        .s_axi_lite_rvalid(s_axi_lite_rvalid),
        .s_axi_lite_rready(s_axi_lite_rready),
        .s_axi_lite_rdata(s_axi_lite_rdata),
        .s_axi_lite_rresp(s_axi_lite_rresp),
        .M_AXI_AWID(M_AXI_AWID),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWLEN(M_AXI_AWLEN),
        .M_AXI_AWSIZE(M_AXI_AWSIZE),
        .M_AXI_AWBURST(M_AXI_AWBURST),
        .M_AXI_AWLOCK(M_AXI_AWLOCK),
        .M_AXI_AWCACHE(M_AXI_AWCACHE),
        .M_AXI_AWPROT(M_AXI_AWPROT),
        .M_AXI_AWQOS(M_AXI_AWQOS),
        .M_AXI_AWUSER(M_AXI_AWUSER),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WLAST(M_AXI_WLAST),
        .M_AXI_WUSER(M_AXI_WUSER),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BID(M_AXI_BID),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BUSER(M_AXI_BUSER),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .M_AXI_ARID(M_AXI_ARID),
        .M_AXI_ARADDR(M_AXI_ARADDR),
        .M_AXI_ARLEN(M_AXI_ARLEN),
        .M_AXI_ARSIZE(M_AXI_ARSIZE),
        .M_AXI_ARBURST(M_AXI_ARBURST),
        .M_AXI_ARLOCK(M_AXI_ARLOCK),
        .M_AXI_ARCACHE(M_AXI_ARCACHE),
        .M_AXI_ARPROT(M_AXI_ARPROT),
        .M_AXI_ARQOS(M_AXI_ARQOS),
        .M_AXI_ARUSER(M_AXI_ARUSER),
        .M_AXI_ARVALID(M_AXI_ARVALID),
        .M_AXI_ARREADY(M_AXI_ARREADY),
        .M_AXI_RID(M_AXI_RID),
        .M_AXI_RDATA(M_AXI_RDATA),
        .M_AXI_RRESP(M_AXI_RRESP),
        .M_AXI_RLAST(M_AXI_RLAST),
        .M_AXI_RUSER(M_AXI_RUSER),
        .M_AXI_RVALID(M_AXI_RVALID),
        .M_AXI_RREADY(M_AXI_RREADY),
        .interrupt(interrupt),
        .write_fifo_overflow(write_fifo_overflow)
    );

    initial begin : initial_state
        integer i;

        // Initialize Inputs
        s_axi_lite_awaddr = 0;
        s_axi_lite_awvalid = 0;
        s_axi_lite_wvalid = 0;
        s_axi_lite_wdata = 0;
        s_axi_lite_wvalid = 0;
        s_axi_lite_bready = 0;
        s_axi_lite_araddr = 0;
        s_axi_lite_arvalid = 0;
        s_axi_lite_rready = 0;
        s_axi_lite_wstrb = 0;

        // Wait Reset rising edge
        @(posedge ARESETN);

        for (i=0; i<10; i=i+1) begin
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
        end

        s_axi_lite_wstrb = 4'b1111;

        // Add stimulus here
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0014, 32'h1000_0000);    // cam_addr write
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0010, 32'h0000_0001);    // cam_addr_ap_vld = 1
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_001C, 32'h2000_0000);    // lap_addr write
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0018, 32'h0000_0001);    // lap_addr_ap_vld = 1
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0008, 32'h0000_0001);    // IP Interrupt Enable Registe(ap_done=1)
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0000, 32'h0000_0001);    // ap_start = 1
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_RADC1(32'h0000_0000);

        forever begin
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
            AXI_MASTER_RADC1(32'h0000_0000);
        end
    end

    // Write Transcation 1
    task AXI_MASTER_WADC1;
        input    [C_S_AXI_LITE_ADDR_WIDTH-1:0]    awaddr;
        input    [C_S_AXI_LITE_DATA_WIDTH-1:0]    wdata;
        begin
            s_axi_lite_awaddr    = awaddr;
            s_axi_lite_awvalid    = 1'b1;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_awvalid <= 1'b0;
            s_axi_lite_wdata = wdata;
            s_axi_lite_wvalid = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
            s_axi_lite_wvalid = 1'b0;
            s_axi_lite_bready = 1'b1;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_bready = 1'b0;
        end
    endtask

    // Read Transcation 1
    task AXI_MASTER_RADC1;
        input    [31:0]    araddr;
        begin
            s_axi_lite_araddr    = araddr;
            s_axi_lite_arvalid     = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_araddr    = 0;
            s_axi_lite_arvalid     = 1'b0;
            s_axi_lite_rready = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_rready = 1'b0;
        end
    endtask

    // clk_gen のインスタンス(ACLK)
    clk_gen #(
        .CLK_PERIOD(100),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(ACLK)
    );
    assign s_axi_lite_aclk = ACLK;

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b0),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(ARESETN),
        .init_done()
    );

    // Instantiate the Unit Under Test (UUT_slave)
    axi_slave_bfm # (
        .C_M_AXI_DATA_WIDTH(32),
        .WRITE_RANDOM_WAIT(1),    // Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
        .READ_RANDOM_WAIT(0),    //  Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
        .READ_DATA_IS_INCREMENT(1),    // ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
        .RUNDAM_BVALID_WAIT(0)
    ) uut_slave (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .M_AXI_AWID(M_AXI_AWID),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWLEN(M_AXI_AWLEN),
        .M_AXI_AWSIZE(M_AXI_AWSIZE),
        .M_AXI_AWBURST(M_AXI_AWBURST),
        .M_AXI_AWLOCK({1'b0, M_AXI_AWLOCK}),
        .M_AXI_AWCACHE(M_AXI_AWCACHE),
        .M_AXI_AWPROT(M_AXI_AWPROT),
        .M_AXI_AWQOS(M_AXI_AWQOS),
        .M_AXI_AWUSER(M_AXI_AWUSER),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WLAST(M_AXI_WLAST),
        .M_AXI_WUSER(M_AXI_WUSER),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BID(M_AXI_BID),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BUSER(M_AXI_BUSER),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .M_AXI_ARID(M_AXI_ARID),
        .M_AXI_ARADDR(M_AXI_ARADDR),
        .M_AXI_ARLEN(M_AXI_ARLEN),
        .M_AXI_ARSIZE(M_AXI_ARSIZE),
        .M_AXI_ARBURST(M_AXI_ARBURST),
        .M_AXI_ARLOCK(M_AXI_ARLOCK),
        .M_AXI_ARCACHE(M_AXI_ARCACHE),
        .M_AXI_ARPROT(M_AXI_ARPROT),
        .M_AXI_ARQOS(M_AXI_ARQOS),
        .M_AXI_ARUSER(M_AXI_ARUSER),
        .M_AXI_ARVALID(M_AXI_ARVALID),
        .M_AXI_ARREADY(M_AXI_ARREADY),
        .M_AXI_RID(M_AXI_RID),
        .M_AXI_RDATA(M_AXI_RDATA),
        .M_AXI_RRESP(M_AXI_RRESP),
        .M_AXI_RLAST(M_AXI_RLAST),
        .M_AXI_RUSER(M_AXI_RUSER),
        .M_AXI_RVALID(M_AXI_RVALID),
        .M_AXI_RREADY(M_AXI_RREADY)
    );

endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end
endmodule

`default_nettype wire

  1. 2013年11月26日 04:20 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

つくばマラソンに出てきました

昨日は奥さんとつくばマラソンに参加してきました。
奥さんと私は阿見アスリートクラブというところに所属しているというか?お世話になっているのですが、ブースを設けてくれてランナーのサポートをして頂いています。コーチ陣が豚汁、すいとん鍋を作ってくれて振る舞ってくれました。また、着替えブースを設置してもらっているのはとっても助かりました。
tukuba_marathon_1_131125.jpg

奥さんは初マラソン、私は初10kmです。
最初に奥さんのマラソンのスタートが9時30分でした。持ちタイム順にAからHまでスタート位置が違っています。スタート位置の様子です。Hです。
tukuba_marathon_2_131125.jpg

これはGの後ろのほうを見たところです。
tukuba_marathon_3_131125.jpg

家の奥さんはスタート順がGだったんですが、スタート位置に辿り着くまでに9分位掛かったそうです。
奥さんが9時30分にスタートした後、10kmに出る人たちでストレッチをして準備をしました。筑波大の陸上競技場を走るのが久しぶりだったので、ジョグをしてきました。
私のスタート位置はDでした。10kmは少ないので、Dが最後です。タイムを70分で申請したので、最後でした。
10時10分にスタートしました。スタートしてから2分位でスタート位置を通過しました。
スタートしてからは、団子状態なので、抜くに抜けずゆっくり行きました。結構、人の割に道が狭く、また集団で走っている人たちもいるので抜くのが難しいです。筑波大学外に出ると折り返しに反対車線を使って、1車線しか走るスペースが無いので、抜くのが難しいです。歩道を走れば抜けるんですけどね。最後に大学内のループに入ってくるとだいぶ集団が伸びて抜きやすくなりました。
走りはと言うと、1kmごとのラップを見ると、6:45/kmから5:50/kmに段々上げていって目標通りだったんですが、最後の100mで疲れてしまい、抜かれてしまいました。もう少し走りこみが必要のようです。最後の頃の陸橋の坂もきつかったです。
タイムは公式タイムが1時間3分53秒で、これは、スタートの合図があったときからです。自分がスタート位置を超えた時からだと、1時間1分50秒でした。目標の65分を上回ることが出来たので、満足です。

奥さんは、目標タイムが4時間だったので、待っていたらなかなか来ません。心配していたら、5時間ちょっと手前でゴールしたそうです。良かった。。。足がつったり、股関節が痛かったり大変だったそうです。不本意な結果だったそうでした。

5時間以上かかっているランナーに聞いたところ、給水所でコップが無くなったということで、水が飲めない給水所が結構あったようです。そこでは、水の入ったバケツに人がたかって、手で水をすくって飲んでいたそうです。昨日は暑かったので、給水する人が多く、コップが無くなってしまったんでしょう?そのランナーは脱水になってふらふらでした。運営がとってもまずいですね。何やっているんでしょう?
来年の改善を望みます。そう言えば、救急車で運ばれる人が多かったです。

ともかく、昨日はとっても良い天気でした。初10kmとしては、良かったと思います。
tukuba_marathon_4_131125.jpg
  1. 2013年11月25日 04:25 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP3(シミュレーション)

AXI4 Master アクセスのラプラシアン・フィルタ IP2(現在作成中)”の続き。

AXI4 Master アクセスのラプラシアン・フィルタ IPが出来てシミュレーションを行った。

プロジェクトのファイル構成を下に示す。
axi4m_lap_filter_3_131124.png

上の図で、lap_filter_axim.v がトップファイルだ。
lap_filter_axim_LiteS_if.v は、Vivado HLS のAXI4 Lite Slaveモジュールを借用している。
axi4_master_inf.v が、作ってきたAXI4 Master アクセス用のIPだ。
line_read_and_y.v は、1ライン画像データを読んできて、RGBからYに変換するモジュールだ。
Dual_Prot_Memory.v は、1ライン分の画像データを保存しておくライン・バッファである。

下にISEのプロジェクトを示す。
axi4m_lap_filter_4_131124.png

プロジェクトのファイル構成の図でも見えていたと思うが、テストベンチ lap_filter_axim_tb.v を作製してシミュレーションを行った。
テストベンチは最初にAXI4 Lite Slave トランザクションでレジスタをセットする。そうすると、AXI4 Master Readトランザクションが発生して、画像データをReadしてくる。Readされた画像データはRGB-Y変換により、輝度値に変換される。画像の輝度値は、ライン・バッファに保存され、3ライン分たまった所でラプラシアン・フィルタ処理を施され、AXI4 Master Write トランザクションにより、ラプラシアン・フィルタ保存領域にWriteされる。
さて、ISimによるシミュレーション結果を見ていこう。
最初に、AXI4 Lite Slave トランザクションでレジスタをセットする部分のシミュレーション結果を見ることにしよう。下にシミュレーション波形を示す。
axi4m_lap_filter_5_131124.png

最初のReadトランザクションを示す。
axi4m_lap_filter_6_131124.png

Read Address Channel は最初に256バースト転送を3回、32バースト転送を行っている。すべてのトランザクションのARIDは0なので、Readトランザクションはネストされ、順番にRead Data Channelでトランザクションが処理される。Read Address Channel のトランザクション波形を示す。(800x600ピクセルのSVGA画面の1行=800ピクセルを256バースト3回と32バースト1回で Read する)
axi4m_lap_filter_7_131124.png

次にWriteトランザクションを示す。最初のWriteトランザクションのデータはすべて0なので、2番めのWriteトランザクションを下に示す。
axi4m_lap_filter_8_131124.png

Write Address Channel のトランザクションを示す。Readトランザクション同様、256バースト転送を3回、32バースト転送を行っている。
axi4m_lap_filter_9_131124.png

下の図では、上が AXI4 Write で下が AXI4 Readになっているので、トランザクションの様子がよくわかると思う。
axi4m_lap_filter_10_131124.png

フレームの最後は、9.8msec 辺だ。AXI4バスの動作周波数は100MHzとなっている。
axi4m_lap_filter_11_131124.png

フレームの最後の後に、AXI4 Lite Slave トランザクションが1つあるのが見えるだろうか?
axi4m_lap_filter_12_131124.png

これは、AXI4 Lite Slave Readトランザクションで、レジスタの0番地をReadしている。
axi4m_lap_filter_13_131124.png

レジスタ0番地のビットアサインを下に示す。


//------------------------Address Info-------------------
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved


シミュレーション波形を見ると、6をReadできているので、ap_done と ap_idle が立っているのがわかる。

因みに、100MHzでWait無しの最高速で9.8msec です。ちょっと危ないですかね? 危ない時は時は、AXI4バスの動作周波数を150MHzにしてみようかな?と思っています。(16.7msec 以内に処理が終わるかな?ということです)
間に合わない時のその他の対処方法としては、DDR3 SDRAMの帯域は余っているはずなので、ReadトランザクションとWriteトランザクションを重ねあわせることができるはずです。

(2013/11/25:追記)
このラプラシアン・フィルタ AXI4 Master IP はハードウェアとしてVerilog HDLで記述したのだが、わざとCでの高位合成結果のHDLに合わせてメモリベースで設計されている。この場合はハードウェアといえどもクロックベースの設計を行っていないので、ソフトウェア同様、フレームに処理が間に合うかどうかを確定できない。
  1. 2013年11月24日 04:34 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP2(現在作成中)

AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)”の構想を元に、現在、AXI4 Master アクセスのラプラシアン・フィルタ IPを作製中だ。
axi4m_lap_filter_2_131121.png

結構、行数が多くなっている。まだ書き終わらない。こうして見ると、Vivado HLSでC言語からHDLを生成してれるのはとっても楽だ。早く、うまくいくようになってほしいと思う。

なお、AXI4 Master アクセスのラプラシアン・フィルタ IPには、今まで作ってきた、AXI4 Master Interfaceモジュールや、AXI Slave BFMなどを使用する予定だ。むしろ、ここで使うために作ってきた。

AXI4 Slave Bus Functional Model (axi_slave_BFM.vhd)
AXI4 Master Interfaceモジュールの作製1(仕様の検討)
AXI4 Master Interfaceモジュールの作製2(シミュレーション)
AXI4 Master Interfaceモジュールの作製3(シミュレーション2)
AXI4 Master Interfaceモジュールの作製4(axi4_master_inf.v のHDLソース)
AXI4 Master Interfaceモジュールの作製5(Write用FIFOのXCO)
AXI4 Master Interfaceモジュールの作製6(Read用FIFOのXCO)

  1. 2013年11月21日 05:25 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

XST に Dual Port Memory を推論させる (Verilog HDL)

XST に Dual Port Memory を推論させようと思い、Verilog HDL のコードを書いて、XST で論理合成、そしてインプリメントを行った。使用するFPGAはZynq-7020、使用するISEのバージョンは14.7。

関連するブログ記事、”VerilogでXSTにBlock RAMを推論させる

Dual Port Memory を実装する Verilog HDL コード、Dual_Port_Memory_test.v を下に示す。(追記:initial文を追加しました)

`default_nettype none

module Dual_Port_Memory_test(/*autoport*/
//output
           dout,
//input
           clk,
           we,
           waddr,
           raddr,
           din);
    input  wire clk;
    input  wire we;
    input  wire [9:0]   waddr;   // 1024
    input  wire [9:0]   raddr;   // 1024
    input  wire [31:0]  din;
    output reg    [31:0]  dout;

    reg  [31:0]  ram  [0:1023];

    initial begin : memory_initialize
        integer i;
        for (i=0; i<1024; i=i+1)
            ram[i] = 0;
    end

    always  @(posedge  clk) begin
        if  (we)
            ram[waddr]  <=  din;

        dout  <=  ram[raddr];
    end

endmodule

`default_nettype wire


論理合成、インプリメント後の Project Navigator を下に示す。
DPM_1_131119.png

FPGA Editor を起動した時の画面を下に示す。
DPM_2_131119.png

RAMB36E1 を1個使用していた。この Verilog HDL コードは使えそうだ。

(追加)
汎用 Dual Port Memory IPとして使えるように書き換えました。

`default_nettype none

module Dual_Port_Memory_test #(
  parameter integer C_MEMORY_SIZE =   1024, // Word Memory Size (not byte)
  parameter integer DATA_BUS_WIDTH =  32    // RAM Data Width
)
(
    input  wire clk,
    input  wire we,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   waddr,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   raddr,
    input  wire [DATA_BUS_WIDTH-1:0]  din,
    output reg  [DATA_BUS_WIDTH-1:0]  dout
);

    // Beyond Circuts, Constant Function in Verilog 2001を参照しました
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction

    reg  [DATA_BUS_WIDTH-1:0]  ram  [0:C_MEMORY_SIZE-1];

    initial begin : memory_initialize
        integer i;
        for (i=0; i<C_MEMORY_SIZE; i=i+1)
            ram[i] = 0;
    end

    always  @(posedge  clk) begin
        if  (we)
            ram[waddr]  <=  din;

        dout  <=  ram[raddr];
    end

endmodule

`default_nettype wire


”parameter integer C_MEMORY_SIZE = 2048”にすると、2つの RAMB36E1 が使われました。
  1. 2013年11月19日 05:39 |
  2. XST
  3. | トラックバック:0
  4. | コメント:0

Sublime Text3の AutoPort機能 と AutoInst機能

Sublime Text3のシェアウェア料金を払って正式ユーザーになりました。

Verilog Automatic パッケージの AutoPort機能 と AutoInst機能を使いたいと思っていたので、やってみました。

まずは、AutoPort機能です。/*autoport*/を入れておきます。

module test2 (/*autoport*/);
input wire[1:0]a;
input wire b;
output reg [2:0]c,d;
inout wire e;

sublime_text3_9_131117.png

SHIFT+F6 を押すと、自動的にポート宣言を入れてくれます。

module test2 (/*autoport*/
//inout
e,
//output
c,
d,
//input
a,
b);
input wire[1:0]a;
input wire b;
output reg [2:0]c,d;
inout wire e;

test1 test1_inst (/*autoinst*/);

sublime_text3_10_131117.png


次は、 AutoInst機能ですが、これは、CTagsソフトウェアとSublime Text3 のCTagsパッケージをインストールする必要があります。これは下位モジュールをインスタンスする際に自動的にポートマッピングしてくれる機能です。

・Windows7の場合は、”exuberant ctags 日本語対応版”の ”Win32版(バイナリのみ) (ec58j2w32bin.zip 162,098 byte)”をインストールする必要があります。私は、Windows7 64bit版でしたが、Win32版でOKでした。

・ZIPを解凍して、出てきた ctags.exe をパスの通っているフォルダにコピーします。私は、C:\Windows\System32 フォルダにコピーしました。

・次に、Preferences -> Package Control から CTags パッケージをSublime Text3 にインストールします。(インストール方法はこちら

前提として、test1.v と test2.v と2つの Verilog HDL ファイルがあるフォルダが有るとします。先ほどAutoPort機能で使用したのが、test2.v です。下の図に示すように、この2つのファイルだけがフォルダに入っています。
sublime_text3_11_131117.png

test1.v の内容です。parameter とポートがありますが、parameter はAutoInst機能の対象ではないみたいです。

module test1 #(
parameter integer aaa = 1,
parameter integer bbb = 2
(/*autoport*/
input wire[1:0]a,
input wire b,
output reg [2:0]c,d,
inout wire e
);

・Sublim Text3 の Findメニューから Ctags -> Rebuild Tags を選択します。
sublime_text3_12_131117.png

・すると、Tagファイルが生成されます。
sublime_text3_13_131117.png

・test2.v の test1 のインスタンスのポート接続を書くところに /*autoinst*/ を書いておきます。

・test2.v の test1 のモジュール名にカーソルを持ってきて、SHIFT+F7 を押します。
sublime_text3_14_131117.png

・test1.v のポートが test2.v の test1モジュールのインスタンスに挿入されます。
sublime_text3_15_131117.png

更に、Alt+S を押すと、現在フォーカスされているファイルのシンボルが一覧表示されて、クリックするとその宣言された行にカーソルが行きます。
sublime_text3_16_131117.png

ALT+SHIFT+S を押すと、フォルダにある全てのファイルのシンボルが一覧表示されます。
sublime_text3_17_131117.png
  1. 2013年11月17日 18:09 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:0

Geany エディタ

Geany というエディタをインストールしました。これもSublime Textと同様に学生実験で学生さんに教えてもらいました。
Geanyのページです。
Download»Releases から Windows なので、geany-1.23.1_setup.exe - Full Installer including GTK 2.16.をインストールしました。

シンボルも表示されて良い感じです。
geany_1_131117.png

シンボルをクリックすると定義されたところに飛びます。
geany_3_131117.png

更に、文字のエンコーディングも日本語のEUCとかSHIFT-JISとか揃っています。
geany_2_131117.png

なかなか良さそうです。
  1. 2013年11月17日 09:39 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)

以前にもラプラシアン・フィルタをFPGAのハードウェアで作ったことがあるが、それは、1連のパイプラインされた構造だった。1ピクセルの画像データが入ってきて、パイプラインにデータが満たされていれば、ラプラシアン・フィルタ後のデータが出てくる構造だ。下にそのブロック図を示す。(”画像のエッジ検出6(3X3での方式の検討)”参照)
edge_detect_11_091111.png

今回はわざとこの構造は取らずに、C言語からHLSで合成したようにシリアライズしてみようと思うのだが、なかなかわざと遅くしようと作ったことがなので、戸惑っている。ともかくC言語からHDLを合成したようにメモリベースで、ある程度シリアライズされた構成で作ってみようと思う。

最初はメモリベースのシングルバッファリングで作ることにした。そのフロー図を下に示す。
axi4m_lap_filter_1_131116.png

上の図の四角い箱の中身は並列に実行する。つまり、”1ライン分ピクセルデータをMemory Readし白黒変換”までをパイプライン化するわけだ。

これで実装してやってみよう。今回は、あえてCでのハードウェア実装にこだわって実力を見てみようと思う。

更に、現在のラインバッファの数は3つだが、ラインバッファの数を4つにすれば、クロックごとに同期しなくてもラインごとに同期すれば、3番目の”1ライン分ピクセルデータをMemory Readし白黒変換”と”1ラインのラプラシアン・フィルタ Memory Wite”を重ねあわせることができるはずだ。これによる性能の向上を見てみようと思う。
  1. 2013年11月16日 09:54 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master Interfaceモジュールの作製6(Read用FIFOのXCO)

”AXI4 Master Interfaceモジュールの作製5(Write用FIFOのXCO)”の続き。

今回は、axi4_master_inf.v で使用されているRead用のFIFOのXCOファイルを貼っておく。これでシミュレーションをするためのファイルが1式揃うので、シミュレーションを行うことができる。

まずは、read_adfifo.xco から下に貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 21:38:12 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=read_adfifo
CSET data_count=false
CSET data_count_width=4
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=false
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Independent_Clocks_Distributed_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Distributed_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Distributed_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Distributed_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=15
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=14
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=40
CSET input_depth=16
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=40
CSET output_depth=16
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=5
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=5
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: d3322e25


次に、read_adfifo_outs.xco を貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 21:31:56 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=read_adfifo_outs
CSET data_count=false
CSET data_count_width=4
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=2
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=3
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=true
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Common_Clock_Distributed_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=0
CSET full_threshold_assert_value=14
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=13
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=8
CSET input_depth=16
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=8
CSET output_depth=16
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=Standard_FIFO
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=4
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Synchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=false
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=4
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: 28a1faa5


最後に、read_fifo.xco を貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 21:19:37 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=true
CSET almost_full_flag=true
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=read_fifo
CSET data_count=false
CSET data_count_width=9
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=false
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Independent_Clocks_Block_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=511
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=510
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=64
CSET input_depth=512
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=64
CSET output_depth=512
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=10
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=10
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: 42518a21


  1. 2013年11月15日 04:31 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master Interfaceモジュールの作製5(Write用FIFOのXCO)

AXI4 Master Interfaceモジュールの作製4(axi4_master_inf.v のHDLソース)”の続き。

今回は、axi4_master_inf.v で使用されているWrite用のFIFOのXCOファイルを貼っておく。

最初に write_adfifo から下に貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 21:28:42 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=write_adfifo
CSET data_count=false
CSET data_count_width=4
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=false
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Independent_Clocks_Distributed_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=15
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=14
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=40
CSET input_depth=16
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=40
CSET output_depth=16
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=5
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=5
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: 520b8a14


次に、write_adfifo_outs を貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 21:22:49 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=false
CSET almost_full_flag=false
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=write_adfifo_outs
CSET data_count=false
CSET data_count_width=5
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=true
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Common_Clock_Distributed_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=0
CSET full_threshold_assert_value=15
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=14
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=8
CSET input_depth=16
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=8
CSET output_depth=16
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=5
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Synchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=5
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: 1efdf94d


次に、write_fifo を貼っておく。

##############################################################
#
# Xilinx Core Generator version 14.7
# Date: Wed Nov 13 20:54:53 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=true
CSET almost_full_flag=true
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=write_fifo
CSET data_count=false
CSET data_count_width=9
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=false
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Independent_Clocks_Block_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=511
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=510
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=72
CSET input_depth=512
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=72
CSET output_depth=512
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=10
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=10
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: f34cfd9c

  1. 2013年11月15日 04:18 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master Interfaceモジュールの作製4(axi4_master_inf.v のHDLソース)

AXI4 Master Interfaceモジュールの作製3(シミュレーション2)”の続き。

AXI4 Masterアクセスをする汎用モジュール axi4_master_inf.v を貼っておく。 axi4_master_inf.v の仕様は”AXI4 Master Interfaceモジュールの作製1(仕様の検討)”に詳しく説明してあるので参考のこと。
テストベンチの貼ってある”AXI4 Master Interfaceモジュールの作製2(シミュレーション)”と一緒に見ると、更に動作がわかりやすいと思う。
但し、axi4_master_inf.v を実機動作させたことはないため、実際に動作するかどうかはわからない?もし使った方がいたら、動作したかどうかをコメント欄でお知らせください。よろしくお願い致します。という訳で、当然、動作の保証はありません。。。
いま、ラプラシアン・フィルタのAXI4 Master IPを自力で作っている途中なのだが、そこには、 axi4_master_inf.v を使用しているので、動作するかどうか?わかると思う。

下に、axi4_master_inf.v を貼っておく。
(2013/11/22:スペルミスのため修正)
(2013/11/26:スペルミスと write_data_empty ポートの追加のために修正)
(2013/12/17:read_adfifo の .wr_clk と .wr_rst が間違っていたので修正した)
(2013/12/19:すべてのFIFOの overflow, underflow にアサーションを追加した)
(2014/02/05 : write_rst, read_rst のリセット条件に init_done = 0 の時のリセットを追加)
(2014/08/27:wr_data_csステートマシンのバグフィックス)

`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Create Date:    03:43:28 10/30/2013
// Design Name:
// Module Name:    axi4_master_inf
// write_adffio, read_adfifo へのデータの投入は基本的に2クロックに1回とする
// 2013/11/04
// 2013/11/25 : write_fifo_empty ポートを追加
// 2013/12/18 : すべての FIFO の overflow と underflow に assertion を追加
// 2014/02/05 : write_rst, read_rst のリセット条件に init_done = 0 の時のリセットを追加
// 2014/08/04 : wr_data_csステートマシンのバグフィックス
//////////////////////////////////////////////////////////////////////////////////
module axi4_master_inf #
  (/*autoport*/
        parameter integer C_INTERCONNECT_M_AXI_WRITE_ISSUING = 8,
        parameter integer C_M_AXI_THREAD_ID_WIDTH       = 1,
        parameter integer C_M_AXI_ADDR_WIDTH            = 32,
        parameter integer C_M_AXI_DATA_WIDTH            = 64,
        parameter integer C_M_AXI_AWUSER_WIDTH          = 1,
        parameter integer C_M_AXI_ARUSER_WIDTH          = 1,
        parameter integer C_M_AXI_WUSER_WIDTH           = 1,
        parameter integer C_M_AXI_RUSER_WIDTH           = 1,
        parameter integer C_M_AXI_BUSER_WIDTH           = 1,
        parameter [31:0]  C_M_AXI_TARGET                 = 32'h00000000,
        parameter integer C_M_AXI_BURST_LEN             = 256,
        parameter integer C_OFFSET_WIDTH                = 32,

        /* Disabling these parameters will remove any throttling.
        The resulting ERROR flag will not be useful */
        parameter integer C_M_AXI_SUPPORTS_WRITE         = 1,
        parameter integer C_M_AXI_SUPPORTS_READ         = 1
    )
    (
        // System Signals
        input wire           ACLK,
        input wire           ARESETN,

        // Master Interface Write Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_AWID,
        output wire [C_M_AXI_ADDR_WIDTH-1:0]          M_AXI_AWADDR,
        output wire [8-1:0]                         M_AXI_AWLEN,
        output wire [3-1:0]                          M_AXI_AWSIZE,
        output wire [2-1:0]                          M_AXI_AWBURST,
        output wire                                  M_AXI_AWLOCK,
        output wire [4-1:0]                          M_AXI_AWCACHE,
        output wire [3-1:0]                          M_AXI_AWPROT,
        // AXI3 output wire [4-1:0]                  M_AXI_AWREGION,
        output wire [4-1:0]                          M_AXI_AWQOS,
        output wire [C_M_AXI_AWUSER_WIDTH-1:0]          M_AXI_AWUSER,
        output wire                                  M_AXI_AWVALID,
        input  wire                                  M_AXI_AWREADY,

        // Master Interface Write Data
        // AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_WID,
        output wire [C_M_AXI_DATA_WIDTH-1:0]          M_AXI_WDATA,
        output wire [C_M_AXI_DATA_WIDTH/8-1:0]          M_AXI_WSTRB,
        output wire                                  M_AXI_WLAST,
        output wire [C_M_AXI_WUSER_WIDTH-1:0]          M_AXI_WUSER,
        output wire                                  M_AXI_WVALID,
        input  wire                                  M_AXI_WREADY,

        // Master Interface Write Response
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_BID,
        input  wire [2-1:0]                          M_AXI_BRESP,
        input  wire [C_M_AXI_BUSER_WIDTH-1:0]          M_AXI_BUSER,
        input  wire                                  M_AXI_BVALID,
        output wire                                  M_AXI_BREADY,

        // Master Interface Read Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_ARID,
        output wire [C_M_AXI_ADDR_WIDTH-1:0]          M_AXI_ARADDR,
        output wire [8-1:0]                          M_AXI_ARLEN,
        output wire [3-1:0]                          M_AXI_ARSIZE,
        output wire [2-1:0]                          M_AXI_ARBURST,
        output wire [2-1:0]                          M_AXI_ARLOCK,
        output wire [4-1:0]                          M_AXI_ARCACHE,
        output wire [3-1:0]                          M_AXI_ARPROT,
        // AXI3 output wire [4-1:0]                  M_AXI_ARREGION,
        output wire [4-1:0]                          M_AXI_ARQOS,
        output wire [C_M_AXI_ARUSER_WIDTH-1:0]          M_AXI_ARUSER,
        output wire                                  M_AXI_ARVALID,
        input  wire                                  M_AXI_ARREADY,

        // Master Interface Read Data
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_RID,
        input  wire [C_M_AXI_DATA_WIDTH-1:0]          M_AXI_RDATA,
        input  wire [2-1:0]                          M_AXI_RRESP,
        input  wire                                  M_AXI_RLAST,
        input  wire [C_M_AXI_RUSER_WIDTH-1:0]          M_AXI_RUSER,
        input  wire                                  M_AXI_RVALID,
        output wire                                  M_AXI_RREADY,

        // User Ports
        input    wire                                 write_clk,
        input    wire                                 write_rst,

        input    wire                                write_adfifo_wr_ena,
        input    wire    [C_M_AXI_ADDR_WIDTH-1:0]    write_adfifo_addr,
        input    wire    [8-1:0]                        write_adfifo_awlen,
        output    wire                                write_adfifo_full,

        input    wire                                write_fifo_wr_ena,
        input    wire    [C_M_AXI_DATA_WIDTH-1:0]    write_fifo_write_data,
        input    wire    [C_M_AXI_DATA_WIDTH/8-1:0]    write_fifo_wstrb,
        output    wire                                write_fifo_full,
        output    wire                                write_fifo_almost_full,
        output    reg                                    write_fifo_empty,

        input    wire                                 read_clk,
        input    wire                                 read_rst,

        input    wire                                read_adfifo_wr_ena,
        input    wire    [C_M_AXI_ADDR_WIDTH-1:0]    read_adfifo_addr,
        input    wire    [8-1:0]                        read_adfifo_arlen,
        output    wire                                read_adfifo_full,

        input    wire                                 read_fifo_rd_ena,
        output    wire    [C_M_AXI_DATA_WIDTH-1:0]    read_fifo_read_data,
        output    wire                                read_fifo_empty_n,
        output    wire                                read_fifo_almost_empty_n,

        output    reg                                 wr_resp_err,    // AIX4 Write Transaction error
        input    wire                                init_done
    );

    /*autodef*/
    parameter [1:0]    RESP_OKAY =        2'b00,
                    RESP_EXOKAY =    2'b01,
                    RESP_SLVERR =    2'b10,
                    RESP_DECERR =    2'b11;
    wire    wadfifo_overflow, wadfifo_underflow, wadfifo_empty;
    wire     wadfifo_rd_en;
    wire     [39:0]    wadfifo_dout;
    parameter         IDLE_WR_ADDR =         1'b0,
                    AWVALID_ASSERT =    1'b1;
    reg     wr_addr_cs;
    reg     awvalid;
    wire     [7:0]    wadf_outs_dout;
    reg     wadf_outs_wr_en;
    wire     wadf_outs_rd_en;
    wire     wadf_outs_full, wadf_outs_overflow, wadf_outs_underflow;
    wire     wadf_outs_empty;
    wire     wdfifo_rd_en;
    wire     wdfifo_overflow, wdfifo_underflow;
    wire     wdfifo_empty, wdfifo_almost_empty;
    reg     wvalid, wvalid_1d;
    wire    [71:0]    wdfifo_din;
    wire     [71:0]    wdfifo_dout;
    parameter    [1:0]    IDLE_WR_DATA =        2'b00,
                        WLAST_COUNT_LOAD =    2'b01,
                        WVALID_ASSERT =        2'b11,
                        WVALID_DEASSERT =    2'b10;
    reg     [1:0]    wr_data_cs, wr_data_cs_b;
    reg     [8:0]    wr_data_cnt;
    reg     wlast;
    reg     [4:0]    wr_resp_cnt;
    wire     bready;
    parameter    [1:0]    IDLE_WR_RESP =        2'b00,
                        WAIT_BVALID =        2'b01,
                        WR_RESP_ERROR =        2'b11;
    reg     [1:0]    wr_resp_cs;

    wire    radfifo_rd_en, radfifo_overflow, radfifo_underflow, radfifo_empty;
    wire    [39:0]    radfifo_dout;
    parameter     IDLE_RD_ADDR =        1'b0,
                ARVALID_ASSERT =    1'b1;
    reg     rd_addr_cs;
    reg     arvalid;
    reg     radf_outs_wr_en;
    wire     radf_outs_rd_en;
    wire     [7:0]    radf_outs_dout;
    wire     radf_outs_full, radf_outs_empty;
    wire     radf_outs_overflow, radf_outs_underflow;
    wire     [63:0]    rdfifo_din;
    wire    [63:0]    rdfifo_dout;
    wire     rdfifo_wr_en, rdfifo_full, rdfifo_almost_full;
    wire     rdfifo_overflow, rdfifo_underflow;
    wire     rdfifo_empty, rdfifo_almost_empty;
    parameter     IDLE_RD_DATA =    1'b0,
                RREADY_ASSERT =    1'b1;
    reg     rd_data_cs;
    reg     rready;

    reg     reset1, reset2;
    wire     reset;
    reg        write_fifo_empty_1d;
    reg     wr_rst_1d, wr_rst_2d;
    wire    wr_rst;
    reg     rd_rst_1d, rd_rst_2d;
    wire    rd_rst;

    // AXI bus Reset
    always @(posedge ACLK) begin : proc_reset
        reset1 <= ~ARESETN | ~init_done;
        reset2 <= reset1;
    end
    assign reset = reset2;

    // Write Reset
    always @(posedge write_clk) begin : proc_wr_rst
        wr_rst_1d <= write_rst | ~init_done;
        wr_rst_2d <= wr_rst_1d;
    end
    assign wr_rst = wr_rst_2d;

    // Read Reset
     always @(posedge read_clk) begin : proc_rd_rst
        rd_rst_1d <= read_rst | ~init_done;
        rd_rst_2d <= rd_rst_1d;
    end
    assign rd_rst = rd_rst_2d;

    // Write Transaction
    assign M_AXI_AWUSER = 0;
    assign M_AXI_WUSER = 0;

    // AXI4 Master Write Address Transaction
    write_adfifo wadfifo (/*autoinst*/
        .wr_clk(write_clk), // input wr_clk
        .wr_rst(wr_rst), // input wr_rst
        .rd_clk(ACLK), // input rd_clk
        .rd_rst(reset), // input rd_rst
        .din({write_adfifo_awlen, write_adfifo_addr}), // input [39 : 0] din
        .wr_en(write_adfifo_wr_ena), // input wr_en
        .rd_en(wadfifo_rd_en), // input rd_en
        .dout(wadfifo_dout), // output [39 : 0] dout
        .full(write_adfifo_full), // output full
        .overflow(wadfifo_overflow), // output overflow
        .empty(wadfifo_empty), // output empty
        .underflow(wadfifo_underflow) // output underflow
    );

    // write_adfifo assertion
    // synthesis translate_off
    always @ (posedge write_clk) begin
        if (wr_rst)
            ;
        else begin
            if (wadfifo_overflow) begin
                $display("%m: at time %t ERROR : wadfifo_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (wadfifo_underflow) begin
                $display("%m: at time %t ERROR : wadfifo_underflow is asserted.",$time);
                $stop;
            end
        end
    end
   // synthesis translate_on

    // write_adfifo にアドレス、転送長が入ってきたら、AXI4 Master Write Address Transactionを発生させる
    // アドレス転送は2クロックに1回
    // Write Address Transaction State Machine
    always @(posedge ACLK) begin : proc_axi4m_wr_addr_tran
       if(reset) begin
               wr_addr_cs <= IDLE_WR_ADDR;
               awvalid <= 1'b0;
       end else begin
               case (wr_addr_cs)
                   IDLE_WR_ADDR :
                       if (~wadfifo_empty & ~wadf_outs_full) begin
                           wr_addr_cs <= AWVALID_ASSERT;
                           awvalid <= 1'b1;
                       end
                   AWVALID_ASSERT :
                       if (M_AXI_AWREADY) begin
                           wr_addr_cs <= IDLE_WR_ADDR;
                           awvalid <= 1'b0;
                       end
                  default : /* default */;
               endcase
       end
    end
    assign M_AXI_AWVALID = awvalid;

    assign wadfifo_rd_en = (awvalid & M_AXI_AWREADY) ? 1'b1 : 1'b0;

    assign M_AXI_AWID = 0;
    assign M_AXI_AWLEN = wadfifo_dout[39:32];
    assign M_AXI_AWADDR = wadfifo_dout[31:0];
    assign M_AXI_AWSIZE = (C_M_AXI_DATA_WIDTH==64) ? 3'b011 : 3'b010; // 8 or 4
    assign M_AXI_AWBURST = 2'b01; // INCR
    assign M_AXI_AWLOCK = 1'b0;
    assign M_AXI_AWCACHE = 3'b011; // 3, Xilinxの推奨値
    assign M_AXI_AWPROT = 3'd0;
    assign M_AXI_AWQOS = 4'd0;

    // Write Outstanding Address Transaction Fifo(WOATF)
    write_adfifo_outs wadfifo_outs (
        .clk(ACLK), // input clk
        .srst(reset), // input srst
        .din(wadfifo_dout[39:32]), // input [7 : 0] din
        .wr_en(wadf_outs_wr_en), // input wr_en
        .rd_en(wadf_outs_rd_en), // input rd_enwad_outs_
        .dout(wadf_outs_dout), // output [7 : 0] dout
        .full(wadf_outs_full), // output full
        .overflow(wadf_outs_overflow), // output overflow
        .empty(wadf_outs_empty), // output empty
        .underflow(wadf_outs_underflow) // output underflow
    );

    // write_adfifo_outs assertion
    // synthesis translate_off
    always @ (posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (wadf_outs_overflow) begin
                $display("%m: at time %t ERROR : wadf_outs_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (wadf_outs_underflow) begin
                $display("%m: at time %t ERROR : wadf_outs_underflow is asserted.",$time);
                $stop;
            end
        end
    end
   // synthesis translate_on

   assign wadf_outs_rd_en = wvalid & wlast & M_AXI_WREADY;

    // wadfifo_outs のwr_en
    always @(posedge ACLK) begin
        if (reset) begin
            wadf_outs_wr_en <= 1'b0;
        end else begin
            if (wr_addr_cs==IDLE_WR_ADDR && wadfifo_empty==1'b0 && wadf_outs_full==1'b0)
                wadf_outs_wr_en <= 1'b1;
            else begin
                wadf_outs_wr_en <= 1'b0;
            end
        end
    end

    assign wdfifo_din = (C_M_AXI_DATA_WIDTH==64) ? {write_fifo_wstrb, write_fifo_write_data} : {4'd0, write_fifo_wstrb, 32'd0, write_fifo_write_data}; // Write Data Bus Width = 64 or 32

    // write_data_fifo
    write_fifo wdfifo (
        .wr_clk(write_clk), // input wr_clk
        .wr_rst(wr_rst), // input wr_rst
        .rd_clk(ACLK), // input rd_clk
        .rd_rst(reset), // input rd_rst
        .din(wdfifo_din), // input [71 : 0] din
        .wr_en(write_fifo_wr_ena), // input wr_en
        .rd_en(wdfifo_rd_en), // input rd_en
        .dout(wdfifo_dout), // output [71 : 0] dout
        .full(write_fifo_full), // output full
        .almost_full(write_fifo_almost_full), // output almost_full
        .overflow(wdfifo_overflow), // output overflow
        .empty(wdfifo_empty), // output empty
        .almost_empty(wdfifo_almost_empty), // output almost_empty
        .underflow(wdfifo_underflow) // output underflow
    );

    // write_fifo assertion
    // synthesis translate_off
    always @ (posedge write_clk) begin
        if (wr_rst)
            ;
        else begin
            if (wdfifo_overflow) begin
                $display("%m: at time %t ERROR : wdfifo_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (wdfifo_underflow) begin
                $display("%m: at time %t ERROR : wdfifo_underflow is asserted.",$time);
                $stop;
            end
        end
    end
   // synthesis translate_on

    assign wdfifo_rd_en = wvalid & M_AXI_WREADY;

    assign M_AXI_WDATA = (C_M_AXI_DATA_WIDTH == 64) ? wdfifo_dout[63:0] : wdfifo_dout[31:0]; // Write Data Bus Width = 64 or 32
    assign M_AXI_WSTRB = (C_M_AXI_DATA_WIDTH == 64) ? wdfifo_dout[71:64] : wdfifo_dout[67:64]; // Write Data Bus Width = 64 or 32

    // AXI4 Write Data Transaction State Machine
    always @(posedge ACLK) begin : proc_WrDataSM
       if(reset) begin
               wr_data_cs <= IDLE_WR_DATA;
               wvalid <= 1'b0;
       end else begin
           case (wr_data_cs)
               IDLE_WR_DATA :
                   if (~wadf_outs_empty & ~wdfifo_empty) begin
                       wvalid <= 1'b1;
                       if (wadf_outs_dout != 8'd0) begin
                           wr_data_cs <= WLAST_COUNT_LOAD;
                       end else begin
                           wr_data_cs <= WVALID_ASSERT;
                       end
                   end
               WLAST_COUNT_LOAD :
                   if (wdfifo_almost_empty) begin
                        wr_data_cs <= WVALID_DEASSERT;
                        wvalid <= 1'b0;
                   end else begin
                        wr_data_cs <= WVALID_ASSERT;
                   end
               WVALID_ASSERT :
                   if ((M_AXI_WREADY==1'b1 && wr_data_cnt==9'd1) || wr_data_cnt==9'd0) begin
                       wr_data_cs <= IDLE_WR_DATA;
                       wvalid <= 1'b0;
                   end else if (wdfifo_almost_empty) begin    // 次でWrite Data が empty(バースト中)
                       wr_data_cs <= WVALID_DEASSERT;
                       wvalid <= 1'b0;
                   end
               WVALID_DEASSERT :
                   if (~wdfifo_empty) begin    // Write Data がFIFOに入った
                       wr_data_cs <= WVALID_ASSERT;
                       wvalid <= 1'b1;
                   end
           endcase
       end
    end
    assign    M_AXI_WVALID = wvalid;

    // 1クロック前の wvalid
    always @(posedge ACLK) begin : proc_wvalid_1d
       if(~ARESETN) begin
            wvalid_1d <= 1'b0;
       end else begin
            wvalid_1d <= wvalid;
       end
    end

    // 以前の wr_data_cs ステートの値
    always @(posedge ACLK) begin : proc_wr_data_cs_b
       if(~ACLK) begin
            wr_data_cs_b <= IDLE_WR_DATA;
       end else begin
            wr_data_cs_b <= wr_data_cs;
       end
    end

    // wr_data_cnt
    always @(posedge ACLK) begin : proc_wr_data_cnt
       if(reset) begin
            wr_data_cnt <= 9'd0;
       end else begin
            if (wr_data_cs == WLAST_COUNT_LOAD) begin
                if (M_AXI_WREADY)
                    wr_data_cnt <= {1'b0, wadf_outs_dout};
                else
                    wr_data_cnt <= {1'b0, wadf_outs_dout} + 9'd1;
            end else if (wvalid) begin
                if (M_AXI_WREADY && wr_data_cnt!=9'd0)
                    wr_data_cnt <= wr_data_cnt - 9'd1;
            end else if (wr_data_cs == IDLE_WR_DATA)
                wr_data_cnt <= 9'd0;
       end
    end

    // wlast
    always @(posedge ACLK) begin : proc_wlast
       if(reset) begin
            wlast <= 1'b0;
       end else begin
            if (wr_data_cs==IDLE_WR_DATA && wadf_outs_empty==1'b0 && wadf_outs_dout==8'd0) begin // Single Transction
                wlast <= 1'b1;
            end else if (wr_data_cs==WVALID_ASSERT && M_AXI_WREADY==1'b1 && wr_data_cnt==9'd2) begin // Burst Transaction
                wlast <= 1'b1;
            end else if (wr_data_cs==WLAST_COUNT_LOAD && M_AXI_WREADY==1'b1 && wadf_outs_dout==8'd1) begin // Burst length = 2
                wlast <= 1'b1;
            end else if (wvalid==1'b1 && M_AXI_WREADY==1'b1 && (wr_data_cnt==9'd1 || wadf_outs_dout==8'd0)) begin
                wlast <= 1'b0;
            end
       end
    end
    assign M_AXI_WLAST = wlast;

    // Write Response Transaction Counter
    // Write Response Transaction の残り数をカウントする
    always @(posedge ACLK) begin : proc_WrRespTranCount
       if(reset) begin
            wr_resp_cnt <= 5'd0;
       end else begin
               if(wr_data_cs_b==IDLE_WR_DATA && (wr_data_cs==WLAST_COUNT_LOAD || wr_data_cs==WVALID_ASSERT)) begin // Write Data Transaction start
                   if (M_AXI_BVALID & bready) // Write Response Transaction が完了
                       wr_resp_cnt <= wr_resp_cnt;
                   else
                       wr_resp_cnt <= wr_resp_cnt + 5'd1;
               end else if (M_AXI_BVALID & bready) // Write Response Transaction が完了
                   wr_resp_cnt <= wr_resp_cnt - 5'd1;
       end
    end

    // Write Response Transaction State Machine
    assign bready = 1'b1;
    assign M_AXI_BREADY = bready;
    always @(posedge ACLK) begin : proc_WrRespTranSM
       if(reset) begin
            wr_resp_cs <= IDLE_WR_RESP;
            wr_resp_err <= 1'b0;
       end else begin
               case (wr_resp_cs)
                   IDLE_WR_RESP :
                       if (wr_resp_cnt > 5'd0)
                           wr_resp_cs <= WAIT_BVALID;
                   WAIT_BVALID :
                       if (M_AXI_BVALID & bready) begin
                           if (M_AXI_BRESP == RESP_OKAY)
                               wr_resp_cs <= IDLE_WR_RESP;
                           else
                               wr_resp_cs <= WR_RESP_ERROR;
                       end
                   WR_RESP_ERROR : begin
                       wr_resp_err <= 1'b1;
                       wr_resp_cs <= IDLE_WR_RESP;
                   end
               endcase
       end
    end

    // write_fifo_empty
    // write_clk に同期する
    always @(posedge write_clk) begin : proc_write_fifo_empty
       if(wr_rst) begin
            write_fifo_empty_1d <= 1'b1;
            write_fifo_empty <= 1'b1;
       end else begin
            write_fifo_empty_1d <= wdfifo_empty;
            write_fifo_empty <= write_fifo_empty_1d;
       end
    end


    // Read Transaction
    assign M_AXI_ARUSER = 0;

    // AXI4 Address Transaction read_adfifo
    read_adfifo radfifo (/*autoinst*/
        .wr_clk(read_clk), // input wr_clk
        .wr_rst(rd_rst), // input wr_rst
        .rd_clk(ACLK), // input rd_clk
        .rd_rst(reset), // input rd_rst
        .din({read_adfifo_arlen, read_adfifo_addr}), // input [39 : 0] din
        .wr_en(read_adfifo_wr_ena), // input wr_en
        .rd_en(radfifo_rd_en), // input rd_en
        .dout(radfifo_dout), // output [39 : 0] dout
        .full(read_adfifo_full), // output full
        .overflow(radfifo_overflow), // output overflow
        .empty(radfifo_empty), // output empty
        .underflow(radfifo_underflow) // output underflow
    );

    // read_adfifo assertion
    // synthesis translate_off
    always @ (posedge read_clk) begin
        if (rd_rst)
            ;
        else begin
            if (radfifo_overflow) begin
                $display("%m: at time %t ERROR : radfifo_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (radfifo_underflow) begin
                $display("%m: at time %t ERROR : radfifo_underflow is asserted.",$time);
                $stop;
            end
        end
    end
    // synthesis translate_on

    // write_adfifo にアドレス、転送長が入ってきたら、AXI4 Master Read Address Transactionを発生させる
    // アドレス転送は2クロックに1回
    // Read Address Transaction State Machine
    always @(posedge ACLK) begin
        if (reset) begin
            rd_addr_cs <= IDLE_RD_ADDR;
            arvalid <= 1'b0;
       end else begin
               case (rd_addr_cs)
                   IDLE_RD_ADDR :
                       if (~radfifo_empty & ~radf_outs_full) begin
                           rd_addr_cs <= ARVALID_ASSERT;
                           arvalid <= 1'b1;
                       end
                   ARVALID_ASSERT :
                       if (M_AXI_ARREADY) begin
                           rd_addr_cs <= IDLE_RD_ADDR;
                           arvalid <= 1'b0;
                       end
                  default : /* default */;
               endcase
       end
    end
    assign M_AXI_ARVALID = arvalid;

    assign radfifo_rd_en = (arvalid & M_AXI_ARREADY) ? 1'b1 : 1'b0;

    assign M_AXI_ARID = 0;
    assign M_AXI_ARLEN = radfifo_dout[39:32];
    assign M_AXI_ARADDR = radfifo_dout[31:0];
    assign M_AXI_ARSIZE = (C_M_AXI_DATA_WIDTH==64) ? 3'b011 : 3'b010; // 8 or 4
    assign M_AXI_ARBURST = 2'b01; // INCR
    assign M_AXI_ARLOCK = 1'b0;
    assign M_AXI_ARCACHE = 3'b011; // 3, Xilinxの推奨値
    assign M_AXI_ARPROT = 3'd0;
    assign M_AXI_ARQOS = 4'd0;

    // Read Outstanding Address Transaction Fifo(WOATF)
    read_adfifo_outs radfifo_outs (
        .clk(ACLK), // input clk
        .srst(reset), // input srst
        .din(radfifo_dout[39:32]), // input [7 : 0] din
        .wr_en(radf_outs_wr_en), // input wr_en
        .rd_en(radf_outs_rd_en), // input rd_enwad_outs_
        .dout(radf_outs_dout), // output [7 : 0] dout
        .full(radf_outs_full), // output full
        .overflow(radf_outs_overflow), // output overflow
        .empty(radf_outs_empty), // output empty
        .underflow(radf_outs_underflow) // output underflow
    );

    // read_adfifo_outs assertion
    // synthesis translate_off
    always @ (posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (radf_outs_overflow) begin
                $display("%m: at time %t ERROR : radf_outs_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (radf_outs_underflow) begin
                $display("%m: at time %t ERROR : radf_outs_underflow is asserted.",$time);
                $stop;
            end
        end
    end
    // synthesis translate_on

   assign radf_outs_rd_en = rready & M_AXI_RVALID & M_AXI_RLAST;

    // radfifo_outs のwr_en
    always @(posedge ACLK) begin
        if (reset) begin
            radf_outs_wr_en <= 1'b0;
        end else begin
            if (rd_addr_cs==IDLE_RD_ADDR && radfifo_empty==1'b0 && radf_outs_full==1'b0)
                radf_outs_wr_en <= 1'b1;
            else begin
                radf_outs_wr_en <= 1'b0;
            end
        end
    end

    // read_data_fifo
    read_fifo rdfifo (
        .wr_clk(ACLK), // input wr_clk
        .wr_rst(reset), // input wr_rst
        .rd_clk(read_clk), // input rd_clk
        .rd_rst(rd_rst), // input rd_rst
        .din(rdfifo_din), // input [63 : 0] din
        .wr_en(rdfifo_wr_en), // input wr_en
        .rd_en(read_fifo_rd_ena), // input rd_en
        .dout(rdfifo_dout), // output [63 : 0] dout
        .full(rdfifo_full), // output full
        .almost_full(rdfifo_almost_full), // output almost_full
        .overflow(rdfifo_overflow), // output overflow
        .empty(rdfifo_empty), // output empty
        .almost_empty(rdfifo_almost_empty), // output almost_empty
        .underflow(rdfifo_underflow) // output underflow
    );

    // read_fifo assertion
    // synthesis translate_off
    always @ (posedge ACLK) begin
        if (reset)
            ;
        else begin
            if (rdfifo_overflow) begin
                $display("%m: at time %t ERROR : rdfifo_overflow is asserted.",$time);
                $stop;
            end
        end
    end
    always @(posedge read_clk) begin
        if (rd_rst)
            ;
        else begin
            if (rdfifo_underflow) begin
                $display("%m: at time %t ERROR : rdfifo_underflow is asserted.",$time);
                $stop;
            end
        end
    end
    // synthesis translate_on

    assign read_fifo_empty_n = ~rdfifo_empty;
    assign read_fifo_almost_empty_n = ~rdfifo_almost_empty;
    assign rdfifo_wr_en = M_AXI_RVALID & rready;
    assign rdfifo_din = (C_M_AXI_DATA_WIDTH == 64) ? M_AXI_RDATA : {32'd0, M_AXI_RDATA}; // Read Data Bus Width = 64 or 32
    assign read_fifo_read_data = (C_M_AXI_DATA_WIDTH == 64) ? rdfifo_dout : rdfifo_dout[31:0]; // Read Data Bus Width = 64 or 32

    // AXI4 Read Data Transaction State Machine
    always @(posedge ACLK) begin : proc_RdDataSM
       if(reset) begin
            rd_data_cs <= IDLE_RD_DATA;
            rready <= 1'b0;
       end else begin
            case (rd_data_cs)
                IDLE_RD_DATA :
                    if (~radf_outs_empty) begin
                        rready <= 1'b1;
                        rd_data_cs <= RREADY_ASSERT;
                    end
                RREADY_ASSERT :
                    if (M_AXI_RVALID & M_AXI_RLAST) begin
                        rready <= 1'b0;
                        rd_data_cs <= IDLE_RD_DATA;
                    end
            endcase
       end
    end
    assign M_AXI_RREADY = rready;

endmodule

`default_nettype wire

  1. 2013年11月14日 05:26 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

AXI4 Slave Bus Functional Model (axi_slave_BFM.vhd)

AXI4 Slave Bus Functional Model (axi_slave_BFM.vhd) を貼っておく。今回のBFMは今まで公開したBFMをアドレス転送をネストできるように変更したものだ。よりXilinx社のAXI Interconnect に近くなったと思う。但し、ネストできるアドレス転送は15なので、より多いと思う。

このBFMは、AXI4 Master に対向する、Slave モジュールだ。
AXI4 Slave BFMは、基本的にRAMを生成する。テストするAXI4 Masterモジュールの Write Transaction でRAMに書き込み、Read Transaction でRAM からRead する。READ_DATA_IS_INCREMENTを0 にすると前述したRAMモードになるが、READ_DATA_IS_INCREMENTを 1 にすると、、Read Transaction でRead できるデータがRAM からではなく、0からインクリメントされるデータになるので、より検証をスムーズにすることができる。
なお、RAMの容量は、C_OFFSET_WIDTH で変更することができる。

動作モード設定用のconstant 値を示す。


WRITE_RANDOM_WAIT : integer := 1; -- Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
READ_RANDOM_WAIT : integer := 0; -- Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
READ_DATA_IS_INCREMENT : integer := 0; -- ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
RUNDAM_BVALID_WAIT : integer := 0 -- Write Data Transaction が終了した後で、BVALID をランダムにWaitする = 1、BVALID をランダムにWaitしない = 0, 31 ~ 0 クロックのWait


Verilog に変換しようといろんなFreeのVHDL2Verilog 変換ツールを試したがことごとく変換できなかった。どうやら最初に package文があるのがダメで、更に下に様な記述がダメみたいだ。

constant ADD_INC_OFFSET : natural := natural(log(real(DATA_BUS_BYTES), 2.0));


という訳で、VHDL版だけとなる。後で、Verilog HDLに手動で変換しても良いかな?と思っている。

それでは、axi_slave_BFM.vhd を下に貼っておく。何かバグが有りましたら、コメント欄でお知らせください。
シミュレーション用 同期FIFO IP”に貼った sync_fifo.v が必要です。

-----------------------------------------------------------------------------
--
-- AXI Master用 Slave Bus Function Mode (BFM)   by marsee
-- axi_slave_BFM.vhd
--
-----------------------------------------------------------------------------
-- 2012/02/25 : M_AXI_AWBURST=1 (INCR) にのみ対応、AWSIZE, ARSIZE = 000 (1byte), 001 (2bytes), 010 (4bytes) のみ対応。
-- 2012/07/04 : READ_ONLY_TRANSACTION を追加。Read機能のみでも+1したデータを出力することが出来るように変更した。

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

package m_seq_bfm_pack is
    function M_SEQ16_BFM_F(mseq16in : std_logic_vector
        )return std_logic_vector;
end package m_seq_bfm_pack;
package body m_seq_bfm_pack is
    function M_SEQ16_BFM_F(mseq16in : std_logic_vector
        )return std_logic_vector is
            variable mseq16 : std_logic_vector(15 downto 0);
            variable xor_result : std_logic;
    begin
        xor_result := mseq16in(15) xor mseq16in(12) xor mseq16in(10) xor mseq16in(8) xor mseq16in(7) xor mseq16in(6) xor mseq16in(3) xor mseq16in(2);
        mseq16 := mseq16in(14 downto 0) & xor_result;
        return mseq16;
    end M_SEQ16_BFM_F;
end m_seq_bfm_pack;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use IEEE.math_real.all;

library work;
use work.m_seq_bfm_pack.all;

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

entity axi_slave_bfm is
  generic (
    C_M_AXI_ID_WIDTH             : integer := 1;
    C_M_AXI_ADDR_WIDTH           : integer := 32;
    C_M_AXI_DATA_WIDTH           : integer := 32;
    C_M_AXI_AWUSER_WIDTH    : integer := 1;
    C_M_AXI_ARUSER_WIDTH    : integer := 1;
    C_M_AXI_WUSER_WIDTH     : integer := 1;
    C_M_AXI_RUSER_WIDTH     : integer := 1;
    C_M_AXI_BUSER_WIDTH      : integer := 1;
    
    C_M_AXI_TARGET            : integer := 0;
    C_OFFSET_WIDTH            : integer := 10; -- 割り当てるRAMのアドレスのビット幅
    C_M_AXI_BURST_LEN        : integer := 256;
    
    WRITE_RANDOM_WAIT        : integer := 1; -- Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
    READ_RANDOM_WAIT        : integer := 0; -- Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
    READ_DATA_IS_INCREMENT    : integer := 0; -- ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
    RUNDAM_BVALID_WAIT        : integer := 0    -- Write Data Transaction が終了した後で、BVALID をランダムにWaitする = 1、BVALID をランダムにWaitしない = 0, 31 ~ 0 クロックのWait
    );
  port(
    -- System Signals
    ACLK    : in std_logic;
    ARESETN : in std_logic;

    -- Master Interface Write Address Ports
    M_AXI_AWID     : in  std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_AWADDR   : in  std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
    M_AXI_AWLEN    : in  std_logic_vector(8-1 downto 0);
    M_AXI_AWSIZE   : in  std_logic_vector(3-1 downto 0);
    M_AXI_AWBURST  : in  std_logic_vector(2-1 downto 0);
    -- M_AXI_AWLOCK   : in  std_logic_vector(2-1 downto 0);
    M_AXI_AWLOCK   : in  std_logic_vector(1 downto 0);
    M_AXI_AWCACHE  : in  std_logic_vector(4-1 downto 0);
    M_AXI_AWPROT   : in  std_logic_vector(3-1 downto 0);
    M_AXI_AWQOS    : in  std_logic_vector(4-1 downto 0);
    M_AXI_AWUSER   : in  std_logic_vector(C_M_AXI_AWUSER_WIDTH-1 downto 0);
    M_AXI_AWVALID  : in  std_logic;
    M_AXI_AWREADY  : out std_logic;

    -- Master Interface Write Data Ports
    M_AXI_WDATA  : in  std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
    M_AXI_WSTRB  : in  std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0);
    M_AXI_WLAST  : in  std_logic;
    M_AXI_WUSER  : in  std_logic_vector(C_M_AXI_WUSER_WIDTH-1 downto 0);
    M_AXI_WVALID : in  std_logic;
    M_AXI_WREADY : out std_logic;

    -- Master Interface Write Response Ports
    M_AXI_BID    : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_BRESP  : out std_logic_vector(2-1 downto 0);
    M_AXI_BUSER  : out std_logic_vector(C_M_AXI_BUSER_WIDTH-1 downto 0);
    M_AXI_BVALID : out std_logic;
    M_AXI_BREADY : in  std_logic;

    -- Master Interface Read Address Ports
    M_AXI_ARID     : in  std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_ARADDR   : in  std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
    M_AXI_ARLEN    : in  std_logic_vector(8-1 downto 0);
    M_AXI_ARSIZE   : in  std_logic_vector(3-1 downto 0);
    M_AXI_ARBURST  : in  std_logic_vector(2-1 downto 0);
    M_AXI_ARLOCK   : in  std_logic_vector(2-1 downto 0);
    M_AXI_ARCACHE  : in  std_logic_vector(4-1 downto 0);
    M_AXI_ARPROT   : in  std_logic_vector(3-1 downto 0);
    M_AXI_ARQOS    : in  std_logic_vector(4-1 downto 0);
    M_AXI_ARUSER   : in  std_logic_vector(C_M_AXI_ARUSER_WIDTH-1 downto 0);
    M_AXI_ARVALID  : in  std_logic;
    M_AXI_ARREADY  : out std_logic;

    -- Master Interface Read Data Ports
    M_AXI_RID    : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_RDATA  : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
    M_AXI_RRESP  : out std_logic_vector(2-1 downto 0);
    M_AXI_RLAST  : out std_logic;
    M_AXI_RUSER  : out std_logic_vector(C_M_AXI_RUSER_WIDTH-1 downto 0);
    M_AXI_RVALID : out std_logic;
    M_AXI_RREADY : in  std_logic
    );

end axi_slave_bfm;

architecture implementation of axi_slave_bfm is

constant    AxBURST_FIXED    : std_logic_vector := "00";
constant    AxBURST_INCR    : std_logic_vector := "01";
constant    AxBURST_WRAP    : std_logic_vector := "10";

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";

constant    DATA_BUS_BYTES     : natural := C_M_AXI_DATA_WIDTH/8; -- データバスのビット幅
constant    ADD_INC_OFFSET    : natural := natural(log(real(DATA_BUS_BYTES), 2.0));

-- wad_fifo field
constant    WAD_FIFO_AWID_HIGH        : natural := 37;
constant    WAD_FIFO_AWID_LOW        : natural := 37;
constant    WAD_FIFO_AWBURST_HIGH    : natural := 36;
constant    WAD_FIFO_AWBURST_LOW    : natural := 35;
constant    WAD_FIFO_AWSIZE_HIGH    : natural := 34;
constant    WAD_FIFO_AWSIZE_LOW        : natural := 32;
constant    WAD_FIFO_ADDR_HIGH        : natural := 31;
constant    WAD_FIFO_ADDR_LOW        : natural := 0;

-- rad_fifo field
constant    RAD_FIFO_ARID_HIGH        : natural := 45;
constant    RAD_FIFO_ARID_LOW        : natural := 45;
constant    RAD_FIFO_ARBURST_HIGH    : natural := 44;
constant    RAD_FIFO_ARBURST_LOW    : natural := 43;
constant    RAD_FIFO_ARSIZE_HIGH    : natural := 42;
constant    RAD_FIFO_ARSIZE_LOW        : natural := 40;
constant    RAD_FIFO_ARLEN_HIGH        : natural := 39;
constant    RAD_FIFO_ARLEN_LOW        : natural := 32;
constant    RAD_FIFO_ADDR_HIGH        : natural := 31;
constant    RAD_FIFO_ADDR_LOW        : natural := 0;

-- RAMの生成
constant    SLAVE_ADDR_NUMBER    : integer := 2**(C_OFFSET_WIDTH - ADD_INC_OFFSET);
type ram_array_def is array (SLAVE_ADDR_NUMBER-1 downto 0) of std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
signal ram_array : ram_array_def := (others => (others => '0'));

-- for write transaction
type write_address_state is (idle_wrad, awr_accept);
type write_data_state is (idle_wrdt, wr_burst);
type write_response_state is (idle_wres, wait_bvalid, bvalid_assert);
signal wradr_cs : write_address_state;
signal wrdat_cs : write_data_state;
signal wrres_cs : write_response_state;
signal addr_inc_step_wr : integer := 1;
signal awready         : std_logic;
signal wr_addr         : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal wr_bid         : std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
signal wr_bresp     : std_logic_vector(1 downto 0);
signal wr_bvalid     : std_logic;
signal m_seq16_wr    : std_logic_vector(15 downto 0);
signal wready        : std_logic;
type wready_state is (idle_wready, assert_wready, deassert_wready);
signal cs_wready : wready_state;
signal cdc_we : std_logic;
signal wad_fifo_full, wad_fifo_empty : std_logic;
signal wad_fifo_almost_full, wad_fifo_almost_empty : std_logic;
signal wad_fifo_rd_en : std_logic;
signal wad_fifo_din : std_logic_vector(37 downto 0);
signal wad_fifo_dout : std_logic_vector(37 downto 0);
signal m_seq16_wr_res    : std_logic_vector(15 downto 0);
signal wr_resp_cnt : std_logic_vector(4 downto 0);

-- for read transaction
type read_address_state is (idle_rda, arr_accept);
type read_data_state is (idle_rdd, rd_burst);
type read_last_state is (idle_rlast, rlast_assert);
signal rdadr_cs : read_address_state;
signal rddat_cs : read_data_state;
signal rdlast : read_last_state;
signal addr_inc_step_rd : integer := 1;
signal arready         : std_logic;
signal rd_addr         : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal rd_axi_count    : std_logic_vector(7 downto 0);
signal rvalid        : std_logic;
signal rlast        : std_logic;
signal m_seq16_rd    : std_logic_vector(15 downto 0);
type rvalid_state is (idle_rvalid, assert_rvalid, deassert_rvalid);
signal cs_rvalid : rvalid_state;
signal read_data_count : std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);

signal reset_1d, reset_2d, reset : std_logic := '1';
signal rad_fifo_full, rad_fifo_empty : std_logic;
signal rad_fifo_almost_full, rad_fifo_almost_empty : std_logic;
signal rad_fifo_rd_en : std_logic;
signal rad_fifo_din : std_logic_vector(45 downto 0);
signal rad_fifo_dout : std_logic_vector(45 downto 0);

component sync_fifo generic (
    constant    C_MEMORY_SIZE     : integer := 512;    -- Word (not byte), 2のn乗
    constant    DATA_BUS_WIDTH    : integer := 32        -- RAM Data Width
);
 port (
    clk                : in    std_logic;
    rst                : in     std_logic;
    wr_en            : in     std_logic;
    din                : in     std_logic_vector(DATA_BUS_WIDTH-1 downto 0);
    full            : out     std_logic;
    almost_full     : out     std_logic;
    rd_en            : in     std_logic;
    dout            : out    std_logic_vector(DATA_BUS_WIDTH-1 downto 0);
    empty            : out    std_logic;
    almost_empty    : out    std_logic
);
end component;

begin
    -- ARESETN をACLK で同期化
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            reset_1d <= not ARESETN;
            reset_2d <= reset_1d;
        end if;
    end process;
    reset <= reset_2d;
    
    -- AXI4バス Write Address State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wradr_cs <= idle_wrad;
                awready <= '0';
            else
                case (wradr_cs) is
                    when idle_wrad =>
                        if M_AXI_AWVALID='1' and wad_fifo_full='0' then -- M_AXI_AWVALID が1にアサートされた
                            wradr_cs <= awr_accept;
                            awready <= '1';
                        end if;
                    when awr_accept => -- M_AXI_AWREADY をアサート
                        wradr_cs <= idle_wrad;
                        awready <= '0';
                end case;
            end if;
        end if;
    end process;
    M_AXI_AWREADY <= awready;
    
    -- M_AXI_AWID & M_AXI_AWBURST & M_AXI_AWSIZE & M_AXI_AWADDR を保存しておく同期FIFO
    wad_fifo_din <= (M_AXI_AWID & M_AXI_AWBURST & M_AXI_AWSIZE & M_AXI_AWADDR);

    wad_fifo : sync_fifo generic map(
        C_MEMORY_SIZE => 16,
        DATA_BUS_WIDTH => 38
    ) port map (
        clk =>            ACLK,
        rst =>            reset,
        wr_en =>         awready,
        din =>            wad_fifo_din,
        full =>            wad_fifo_full,
        almost_full =>    wad_fifo_almost_full,
        rd_en =>        wad_fifo_rd_en,
        dout =>            wad_fifo_dout,
        empty =>         wad_fifo_empty,
        almost_empty =>    wad_fifo_almost_empty
    );
    wad_fifo_rd_en <= '1' when wready='1' and M_AXI_WVALID='1' and M_AXI_WLAST='1' else '0';

    -- AXI4バス Write Data State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then
            if reset='1' then
                wrdat_cs <= idle_wrdt;
            else
                case( wrdat_cs ) is
                    when idle_wrdt =>
                        if wad_fifo_empty='0' then -- AXI Write アドレス転送の残りが1個以上ある
                            wrdat_cs <= wr_burst;
                        end if;
                    when wr_burst => -- Writeデータの転送
                        if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
                            wrdat_cs <= idle_wrdt;
                        end if;
                    when others =>
                
                end case ;
            end if;
        end if;
    end process;

    -- m_seq_wr、16ビットのM系列を計算する
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                m_seq16_wr <= (0 => '1', others => '0');
            else
                if WRITE_RANDOM_WAIT=1 then -- Write Transaction 時にランダムなWaitを挿入する
                    if wrdat_cs=wr_burst and M_AXI_WVALID='1' then
                        m_seq16_wr <= M_SEQ16_BFM_F(m_seq16_wr);
                    end if;
                else -- Wait無し
                    m_seq16_wr <= (others => '0');
                end if;
            end if;
        end if;
    end process;
                
    -- wready の処理、M系列を計算して128以上だったらWaitする。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                cs_wready <= idle_wready;
                wready <= '0';
            else
                case (cs_wready) is
                    when idle_wready =>
                        if wrdat_cs=idle_wrdt and wad_fifo_empty='0' then -- 次はwr_burst
                            if m_seq16_wr(7)='0' then -- wready='1'
                                cs_wready <= assert_wready;
                                wready <= '1';
                            else -- m_seq16_wr(7)='1' then -- wready='0'
                                cs_wready <= deassert_wready;
                                wready <= '0';
                            end if;
                        end if;
                    when assert_wready => -- 一度wreadyがアサートされたら、1つのトランザクションが終了するまでwready='1'
                        if wrdat_cs=wr_burst and M_AXI_WLAST='1' and M_AXI_WVALID='1' then -- 終了
                            cs_wready <= idle_wready;
                            wready <= '0';
                        elsif wrdat_cs=wr_burst and M_AXI_WVALID='1' then -- 1つのトランザクション終了。
                            if m_seq16_wr(7)='1' then
                                cs_wready <= deassert_wready;
                                wready <= '0';
                            end if;
                        end if;
                    when deassert_wready =>
                        if m_seq16_wr(7)='0' then -- wready='1'
                            cs_wready <= assert_wready;
                            wready <= '1';
                        end if;
                end case;
            end if;
        end if;
    end process;
    
    M_AXI_WREADY <= wready;
    cdc_we <= '1' when wrdat_cs=wr_burst and wready='1' and M_AXI_WVALID='1' else '0';
    
    -- addr_inc_step_wr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                addr_inc_step_wr <= 1;
            else
                if wrdat_cs=idle_wrdt and wad_fifo_empty='0' then
                    case (wad_fifo_dout(WAD_FIFO_AWSIZE_HIGH downto WAD_FIFO_AWSIZE_LOW)) is
                        when "000" => -- 8ビット転送
                            addr_inc_step_wr <= 1;
                        when "001" => -- 16ビット転送
                            addr_inc_step_wr <= 2;
                        when "010" => -- 32ビット転送
                            addr_inc_step_wr <= 4;
                        when "011" => -- 64ビット転送
                            addr_inc_step_wr <= 8;
                        when "100" => -- 128ビット転送
                            addr_inc_step_wr <= 16;
                        when "101" => -- 256ビット転送
                            addr_inc_step_wr <= 32;
                        when "110" => -- 512ビット転送
                            addr_inc_step_wr <= 64;
                        when others => --"111" => -- 1024ビット転送
                            addr_inc_step_wr <= 128;
                    end case;
                end if;
            end if;
        end if;
    end process;
    
    -- wr_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_addr <= (others => '0');
            else
                if wrdat_cs=idle_wrdt and wad_fifo_empty='0' then
                    wr_addr <= wad_fifo_dout(C_OFFSET_WIDTH-1 downto 0);
                elsif wrdat_cs=wr_burst and M_AXI_WVALID='1' and wready='1' then -- アドレスを進める
                    wr_addr <= wr_addr + addr_inc_step_wr;
                end if;
            end if;
        end if;
    end process;
    
    -- wr_bid の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bid <= "0";
            else
                if wrdat_cs=idle_wrdt and wad_fifo_empty='0' then
                    wr_bid <= wad_fifo_dout(WAD_FIFO_AWID_HIGH downto WAD_FIFO_AWID_LOW);
                end if;
            end if;
        end if;
    end process;
    M_AXI_BID <= wr_bid;
    
    -- wr_bresp の処理
    -- M_AXI_AWBURSTがINCRの時はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bresp <= (others => '0');
            else
                if wrdat_cs=idle_wrdt and wad_fifo_empty='0' then
                    if wad_fifo_dout(WAD_FIFO_AWBURST_HIGH downto WAD_FIFO_AWBURST_LOW)=AxBURST_INCR then -- バーストタイプがアドレス・インクリメントタイプ
                        wr_bresp <= RESP_OKAY; -- Write Transaction は成功
                    else
                        wr_bresp <= RESP_SLVERR; -- エラー
                    end if;
                end if;
            end if;
        end if;
    end process;
    M_AXI_BRESP <= wr_bresp;
    
    -- wr_bvalid の処理
    -- Write Transaction State Machineには含まない。axi_master のシミュレーションを見ると1クロックで終了しているので、長い間、Master側の都合でWaitしていることは考えない。
    -- 次のWrite転送まで遅延しているようであれば、Write Transaction State Machine に入れてブロックすることも考える必要がある。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wrres_cs <= idle_wres;
                wr_bvalid <= '0';
            else
                case( wrres_cs ) is
                    when idle_wres =>
                        if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
                            if m_seq16_wr_res = 0 or RUNDAM_BVALID_WAIT=0 then
                                wrres_cs <= bvalid_assert;
                                wr_bvalid <= '1';
                            else
                                wrres_cs <= wait_bvalid;
                            end if;
                        end if;
                    when wait_bvalid =>
                        if wr_resp_cnt = 0 then
                            wrres_cs <= bvalid_assert;
                            wr_bvalid <= '1';
                        end if;
                    when bvalid_assert =>
                        wrres_cs <= idle_wres;
                        wr_bvalid <= '0';
                    when others =>
                
                end case ;
            end if;
        end if;
    end process;
    M_AXI_BVALID <= wr_bvalid;
    M_AXI_BUSER <= (others => '0');

    -- wr_resp_cnt
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_resp_cnt <= (others => '0');
            else
                if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
                    wr_resp_cnt <= m_seq16_wr_res(4 downto 0);
                elsif wr_resp_cnt /= 0 then
                    wr_resp_cnt <= wr_resp_cnt - 1;
                end if;
            end if;
        end if;
    end process;

    -- m_seq_wr_res、16ビットのM系列を計算する
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                m_seq16_wr_res <= (0 => '1', others => '0');
            else
                m_seq16_wr_res <= M_SEQ16_BFM_F(m_seq16_wr_res);
            end if;
        end if;
    end process;
    
    
    -- AXI4バス Read Address Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdadr_cs <= idle_rda;
                arready <= '0';
            else
                case (rdadr_cs) is
                    when idle_rda =>
                        if M_AXI_ARVALID='1' and rad_fifo_full='0' then -- Read Transaction 要求
                            rdadr_cs <= arr_accept;
                            arready <= '1';
                        end if;
                    when arr_accept => -- M_AXI_ARREADY をアサート
                        rdadr_cs <= idle_rda;
                        arready <= '0';
                end case;
            end if;
        end if;
    end process;
    M_AXI_ARREADY <= arready;

    -- M_AXI_ARID & M_AXI_ARBURST & M_AXI_ARSIZE & M_AXI_ARLEN & M_AXI_ARADDR を保存しておく同期FIFO
    rad_fifo_din <= (M_AXI_ARID & M_AXI_ARBURST & M_AXI_ARSIZE & M_AXI_ARLEN & M_AXI_ARADDR);

    rad_fifo : sync_fifo generic map (
        C_MEMORY_SIZE =>    16,
        DATA_BUS_WIDTH =>    46
    ) port map (
        clk =>            ACLK,
        rst =>            reset,
        wr_en =>        arready,
        din =>             rad_fifo_din,
        full =>            rad_fifo_full,
        almost_full =>    rad_fifo_almost_full,
        rd_en =>        rad_fifo_rd_en,
        dout =>            rad_fifo_dout,
        empty =>        rad_fifo_empty,
        almost_empty =>    rad_fifo_almost_empty
    );
    rad_fifo_rd_en <= '1' when rvalid='1' and M_AXI_RREADY='1' and rlast='1' else '0';

    -- AXI4バス Read Data Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rddat_cs <= idle_rdd;
            else
                case (rddat_cs) is
                    when idle_rdd =>
                        if rad_fifo_empty='0' then -- AXI Read アドレス転送の残りが1個以上ある
                            rddat_cs <= rd_burst;
                        end if;
                    when rd_burst =>
                        if rd_axi_count=0 and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了
                            rddat_cs <= idle_rdd;
                        end if;
                end case;
            end if;
        end if;
    end process;

    -- m_seq_rd、16ビットのM系列を計算する
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                m_seq16_rd <= (others => '1'); -- Writeとシードを変更する
            else
                if READ_RANDOM_WAIT=1 then -- Read Transaciton のデータ転送でランダムなWaitを挿入する場合
                    if rddat_cs=rd_burst and M_AXI_RREADY='1' then
                        m_seq16_rd <= M_SEQ16_BFM_F(m_seq16_rd);
                    end if;
                else -- Wati無し
                    m_seq16_rd <= (others => '0');
                end if;
            end if;
        end if;
    end process;
                
    -- rvalid の処理、M系列を計算して128以上だったらWaitする。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                cs_rvalid <= idle_rvalid;
                rvalid <= '0';
            else
                case (cs_rvalid) is
                    when idle_rvalid =>
                        if rddat_cs=idle_rdd and rad_fifo_empty='0' then -- 次はrd_burst
                            if m_seq16_rd(7)='0' then -- rvalid='1'
                                cs_rvalid <= assert_rvalid;
                                rvalid <= '1';
                            else -- m_seq16_rd(7)='1' then -- rvalid='0'
                                cs_rvalid <= deassert_rvalid;
                                rvalid <= '0';
                            end if;
                        end if;
                    when assert_rvalid => -- 一度rvalidがアサートされたら、1つのトランザクションが終了するまでrvalid='1'
                        if rddat_cs=rd_burst and rlast='1' and M_AXI_RREADY='1' then -- 終了
                            cs_rvalid <= idle_rvalid;
                            rvalid <= '0';
                        elsif rddat_cs=rd_burst and M_AXI_RREADY='1' then -- 1つのトランザクション終了。
                            if m_seq16_rd(7)='1' then
                                cs_rvalid <= deassert_rvalid;
                                rvalid <= '0';
                            end if;
                        end if;
                    when deassert_rvalid =>
                        if m_seq16_rd(7)='0' then -- rvalid='1'
                            cs_rvalid <= assert_rvalid;
                            rvalid <= '1';
                        end if;
                end case;
            end if;
        end if;
    end process;
    
    M_AXI_RVALID <= rvalid;
    
    -- addr_inc_step_rd の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                addr_inc_step_rd <= 1;
            else
                if rddat_cs=idle_rdd and rad_fifo_empty='0' then
                    case (rad_fifo_dout(RAD_FIFO_ARSIZE_HIGH downto RAD_FIFO_ARSIZE_LOW)) is
                        when "000" => -- 8ビット転送
                            addr_inc_step_rd <= 1;
                        when "001" => -- 16ビット転送
                            addr_inc_step_rd <= 2;
                        when "010" => -- 32ビット転送
                            addr_inc_step_rd <= 4;
                        when "011" => -- 64ビット転送
                            addr_inc_step_rd <= 8;
                        when "100" => -- 128ビット転送
                            addr_inc_step_rd <= 16;
                        when "101" => -- 256ビット転送
                            addr_inc_step_rd <= 32;
                        when "110" => -- 512ビット転送
                            addr_inc_step_rd <= 64;
                        when others => -- "111" => -- 1024ビット転送
                            addr_inc_step_rd <= 128;
                    end case;
                end if;
            end if;
        end if;
    end process;
    
    -- rd_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_addr <= (others => '0');
            else
                if rddat_cs=idle_rdd and rad_fifo_empty='0' then
                    rd_addr <= rad_fifo_dout(C_OFFSET_WIDTH-1 downto 0);
                elsif rddat_cs=rd_burst and M_AXI_RREADY='1' and rvalid='1' then
                    rd_addr <= rd_addr + addr_inc_step_rd;
                end if;
            end if;
        end if;
    end process;
    
    -- rd_axi_count の処理(AXIバス側のデータカウント)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_axi_count <= (others => '0');
            else
                if rddat_cs=idle_rdd and rad_fifo_empty='0' then -- rd_axi_count のロード
                    rd_axi_count <= rad_fifo_dout(RAD_FIFO_ARLEN_HIGH downto RAD_FIFO_ARLEN_LOW);
                elsif rddat_cs=rd_burst and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction が1つ終了
                    rd_axi_count <= rd_axi_count - 1;
                end if;
            end if;
        end if;
    end process;
    
    -- rdlast State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdlast <= idle_rlast;
                rlast <= '0';
            else
                case (rdlast) is
                    when idle_rlast =>
                        if rd_axi_count=1 and rvalid='1' and M_AXI_RREADY='1' then -- バーストする場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        elsif rddat_cs=idle_rdd and rad_fifo_empty='0' and rad_fifo_dout(RAD_FIFO_ARLEN_HIGH downto RAD_FIFO_ARLEN_LOW)=0 then -- 転送数が1の場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        end if;
                    when rlast_assert => 
                        if rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了(rd_axi_count=0は決定)
                            rdlast <= idle_rlast;
                            rlast <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process;
    M_AXI_RLAST <= rlast;
    
    -- M_AXI_RID, M_AXI_RUSER の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                M_AXI_RID <= (others => '0');
            else
                if rddat_cs=idle_rdd and rad_fifo_empty='0' then
                    M_AXI_RID <= rad_fifo_dout(RAD_FIFO_ARID_HIGH downto RAD_FIFO_ARID_LOW);
                end if;
            end if;
        end if;
    end process;
    M_AXI_RUSER <= (others => '0');
    
    -- M_AXI_RRESP は、M_AXI_ARBURST がINCR の場合はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                M_AXI_RRESP <= (others => '0');
            else
                if rddat_cs=idle_rdd and rad_fifo_empty='0' then
                    if rad_fifo_dout(RAD_FIFO_ARBURST_HIGH downto RAD_FIFO_ARBURST_LOW)=AxBURST_INCR then
                        M_AXI_RRESP <= RESP_OKAY;
                    else
                        M_AXI_RRESP <= RESP_SLVERR;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    -- RAM
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if cdc_we='1' then
                for i in 0 to C_M_AXI_DATA_WIDTH/8-1 loop
                    if M_AXI_WSTRB(i)='1' then -- Byte Enable
                        ram_array(CONV_INTEGER(wr_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET)))(i*8+7 downto i*8) <= M_AXI_WDATA(i*8+7 downto i*8);
                    end if;
                end loop;
            end if;
        end if;
    end process;

    -- Read Transaciton の時に +1 されたReadデータを使用する(Read 毎に+1)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                read_data_count <= (others => '0');
            else
                if rddat_cs=rd_burst and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction が1つ終了
                    read_data_count <= read_data_count + 1;
                end if;
            end if;
        end if;
    end process;
    
    M_AXI_RDATA <= ram_array(CONV_INTEGER(rd_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET))) when READ_DATA_IS_INCREMENT=0 else read_data_count;
    
end implementation;

  1. 2013年11月13日 04:47 |
  2. AXI4バス
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master Interfaceモジュールの作製3(シミュレーション2)

AXI4 Master Interfaceモジュールの作製2(シミュレーション)”の続き。

前回は、AXI Slave BFM がアドレス転送がネストできないので、アドレス転送のネストにも対応できるように AXI Slave BFM を書き換えた。そのため、シミュレーション用 同期FIFO IPを作製して使用した。
今度の AXI4 Slave BFM には、設定が4つある。それを下に示す。

WRITE_RANDOM_WAIT : integer := 1; -- Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
READ_RANDOM_WAIT : integer := 0; -- Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
READ_DATA_IS_INCREMENT : integer := 0; -- ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
RUNDAM_BVALID_WAIT : integer := 0 -- Write Data Transaction が終了した後で、BVALID をランダムにWaitする = 1、BVALID をランダムにWaitしない = 0, 31 ~ 0 クロックのWait


AXI Slalve BFMを下の設定にしてシミュレーションを行った。

.C_M_AXI_DATA_WIDTH(64),
.WRITE_RANDOM_WAIT(1), // Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_RANDOM_WAIT(1), // Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_DATA_IS_INCREMENT(1), // ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
.RUNDAM_BVALID_WAIT(1)


シミュレーション結果を下に示す。まずは Write Transaction を示す。AXI バスのクロックは200MHz、ユーザー回路側のクロックは149MHz程度だ。
axi4_master_inf_5_131112.png

次に Read Transaction を示す。
axi4_master_inf_6_131112.png

アドレス転送がネストできているのがわかると思う。Write Response の完了まで待たないで、次のデータ転送が始まっている。Zynqで、PLからPSのDDR3 SDRAM コントローラにデータをWriteすると Write Response が帰ってくるのが遅いので、Writeのデータ転送を重ね合わせできれば、スループットが改善できると思う。

テストベンチは、上に示した AXI Slave BFM の設定値以外は、”AXI4 Master Interfaceモジュールの作製2(シミュレーション)”で貼ったテストベンチと同じだ。以前のシミュレーション波形と見比べると、今回のシミュレーション波形がアドレス転送をネスト出来て、データ転送を重ねあわせることができているのがわかると思う。

次に、AXI Slalve BFMを下の設定に変更してシミュレーションを行った。

.C_M_AXI_DATA_WIDTH(64),
.WRITE_RANDOM_WAIT(0), // Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_RANDOM_WAIT(0), // Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_DATA_IS_INCREMENT(1), // ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
.RUNDAM_BVALID_WAIT(0)


これで、Waitなしの最速の状態だ。
シミュレーション結果を下に示す。まずは Write Transaction を示す。
axi4_master_inf_7_131112.png

次に、Read Transaction を示す。
axi4_master_inf_8_131112.png

axi_slave_BFM.vhd は、773行になってしまった。ブログに貼るのが辛いかな?
  1. 2013年11月12日 04:43 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

坂東ハーフマラソン、FPGAXに参加

今日は、坂東いわい将門ハーフマラソンの5Kmの部に参加してから、FPGAXで発表してきました。

朝、6時30分ころ家を車で出発して7時ちょっと過ぎに坂東マラソンに会場に着きました。すでにすごい車の量です。交通の便はあまり良くないので、ほとんどの人が車で来ると思います。
奥さんの10kmのスタートは10時10分、5kmのスタートは10時20分なので、最初はプラプラ歩いてお店のテントを見ていました。ここにはランナーに関係するグッズ、ウェアとかサングラスとかGPSウォッチなどを並べいているお店のテントが6つ位ありました。そこを冷やかしていると、今日は結構寒いのに手袋を忘れたことを思い出して手袋を買いました。680円でした。
その後、会場内のトラックをゆっくり2周して、ストレッチを行いました。
bando_1_131110.jpg

そうそう、有森裕子さんがゲストで来ていました。かなり元気ですね。ランナーとハイタッチしていました。うちの奥さんもハイタッチしたそうです。
bando_2_131110.jpg

ゼッケンを安全ピン4個で付けます。これにはNFCのICタグが入っていて、スタート地点とゴール地点のセンサを通過することで、タイムを自動的に計測してくれます。

奥さんの10kmが10時10分にスタートしてから、上着を置いて、長袖シャツ1枚になって、スタート地点へ。しまった、帽子をかぶってきちゃいました。仕方がないので、そのままスタート。
最初は6分30秒/km くらいで走ってました。人を抜いて上がっていきます。走りだして500mくらいで、5分45秒/km位になってしまったので、少しペースを抑えて、5分55秒/kmくらいにします。
岩井の町の中を通って、折り返しがスタートから2.94kmくらいでした。結構苦しいです。給水があったので、取りました。普通は5kmくらいでは給水を取ることは無いのですが、どうしても1度取ってみたかったので、もらって飲んでみました。スポーツドリンクだったんですが、とても薄く水みたいでした。

最後は、下り坂なので、加速して数人抜きました。そこを過ぎるとトラックに入ります。最後にスパートして5人くらい抜きました。5kmで29分48秒でした。年代別で55位です。給水で20~30秒ロスしましたが、それでも30分を切れたので、満足です。

奥さんは10kmを52分台で、年代別で9位でした。調子が良く50分台だったらお立ち台でしたね。6位までお立ち台がありました。

その後、レタス(田舎なので野菜をもらえます)豚汁サービスとバナナ、とアクエリアスをもらいました。

すぐに家に帰って、着替えて、今度はFPGAXのために東京に行きました。
やはり、疲れていますね。電車で居眠りしていました。体力がなくなっているため、コンビニで甘いものを買って食べながら会場へ。会場のビルの下には関係者が集まっていました。そこの会社の方に案内されて会場に。

最初のFPGA vs GPU の話を聞きながら、次の私の話と対極にあるなと感じていました。正直美味しかったです。つまり、次の私の話と対比がとっても面白いと感じました。

私の話は、いろいろな方に話すのに、ちょっとわかりにくかったかな?と思いましたが、文句は出ませんでしたね。

高位合成の話は、正直よくわからなかったんですが、凄いというのは分かりました。

次はビールとピザで乾杯です。私はビールは飲めないので、お茶で。ピザはたくさんありました。美味しかったです。

Moving Computation to the Data はとっても興味深い内容でした。私が今やっていることとも共通点がありました。

今日はUSTされているのを忘れちゃって、ちょっと言い過ぎたところもありましたが、どうぞご勘弁ください。
とても楽しかったです。またFPGXに参加したいと思います。

資料は公開したほうが良いでしょうか? SlideShareで公開すれば良いのかな?これって後で消せるのだろうか?

(2013/11/11:追記)
FPGAXで発表したプレゼン資料を公開しました。
  1. 2013年11月10日 23:59 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado HLSの現状について

今日のfpgaxで、Vivado HLSについて説明不足があったので、ブログで現状を解説します。

・Vivado HLS 2013.2
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにして、IP化した。そのIPをソフトウェアから呼び出して使用した。動作を確認すると、完全に動作しました。

Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする1
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする2
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする3


このラプラシアン・フィルタの axi lite slave IP を、使ってみたのが、下のブログだ。

Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる1
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる2
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする3
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる3


ソフトウェアの実行時間は、約1.94秒となった。完全にソフトウェアで実行した前回の 1.94 / 0.39 ≒ 5 倍になった。遅くなってしまった。AXI4 Lite Slaveバスのアクセスがとっても多いので仕方が無いかもしれない。でラプラシアン・フィルタ式のみをaxi lite slave IP として使用した時のCソースはここに貼ってある
Vivado HLSでAXI4 Lite Slave IPを作ることは、私の例では問題ない。但し、ラプラシアン・フィルタ程度ではハードウェアにオフロードしたほうが遅くなる。

そこで、AXI4 Masterで1画面分のラプラシアン・フィルタを行うIPを作ることにした。

Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする1
 ・laplacian_filter.c を Vivado HLS でコンパイルできるように書き換えてIPにした。
Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする2
 ・前回は、カメラ画像フレーム・バッファ読み込み用アドレスとラプラシアン・フィルタの結果を書き出すフレーム・バッファのアドレスは、parameter 指定の固定アドレスだったので、AXI4 Lite Slave でAXI4 Master のRead/Writeするアドレスを渡す仕様に変更した。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う1
 ・”Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする2”で作ったAXI4 Lite Slave と AXI4 Master の 2種類のAXIバスを実装するラプラシアン・フィルタ IPをXPSのカスタムIPとして使ってみた。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う2
 ・デバックしているが、いまのところ ap_done が上がらずに原因を調査中。Vivado HLSでのSystemC のCo-Simulation をしたところ訳の分からないエラーになった。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う3
ChipScopeで調査したところ、ラプラシアン・データを書き戻すAXI4 Master Writeのアクセスが1個も来ていなかった。これによりペンディングとなる。


・Vivado HLS 2013.3

Vivado HLS 2013.3でラプラシアン・フィルタ関数をaxi masterモジュールにする
 ・Vivado 2013.3 をインストールした。そして、再度、Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにしてみた。
 ・Vivado HLS 2013.3 でも、C Simulation と C/RTL Cosimulation はうまく行かなかった。
 ・IP化は出来た。
Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1
 ・ソースファイルを貼り付けた。
 ・AXI4 Master 版ラプラシアン・フィルタを動作されるソフトウェアを実行したが、ap_done が帰ってこない。Vivado 2013.2 の時とソフト的には同様の結果だった。
Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う2
 Vivado HLS 2013.3 で生成されたラプラシアン・フィルタIPには2つの問題がある。
 1.ap_doneが 1 にならない。
 2.ラプラシアン・フィルタのWriteデータが全て 0 になっている。(最初のラインはすべて0を書いているので、これは正しいです。他のラインがどうなっているかを確認します)

というように、Vivado HLS の AXI4 Lite Slave IPは完璧に動作しているので問題ない。しかし、Vivado HLSを使用した AXI4 Master IP は Co-Simulation が出来ないことや、動作しないという問題がある。私のコードが悪いのかもしれないが、実際のAXI4 Master Write の動作は改善が見られるので、まだ発展状態ではないか?と思った。

(追加)
Vivado HLSについては、pragma でAXI4 Lite 、AXI4 Master 、AXI4 Stream バスも指定することが出来て、簡単にAXIバスIPが書けるので気に入っています。それに、生成されたHDLコードも読みやすいです。その中には、AXI4 Master汎用IPとして使えそうなモジュールもあります。まだ、たぶん(私のコードやマニュアルの読み方が間違っていなければ)発展途上だと思っているので、AXI4 Master IPについては、もう1パージョン待ってみようと思っています。
  1. 2013年11月10日 22:57 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

シミュレーション用 同期FIFO IP

AXI4 Master Interfaceモジュールの作製2(シミュレーション)”で”axi_slave_BFM.v を変更して、ネストされたアドレス転送を受け付けることにした。そのためには、ネストされたReadアドレス転送を溜めておくためにFIFOが必要となる。それで、シミュレーションに使用するために汎用の同期FIFO を作ることにした。

シミュレーション用に、Verilog HDLを使用して、汎用に使える同期FIFOを書いた。
更に、テストベンチも作ってISEでシミュレーションを行った。そのシミュレーション波形を下に示す。
sync_fifo_3_131109.png

ちなみに、シミュレーション用で簡単に作ってあるが、論理合成、インプリメントもできる。出力がFFを通っていないので、予想通りにSLICEMにマップされた。
下にProject Navigator の画面を示す。
sync_fifo_1_131109.png

下にFPGA Editor の画面を示す。
sync_fifo_2_131109.png

シミュレーション用 同期FIFO sync_fifo.v を下に貼っておく。

// Synchronous FIFO for Simulation
//
// 2013/11/08 by marsee
//
// ライセンスは二条項BSDライセンス (2-clause BSD license)とします。

`default_nettype none

module sync_fifo #(
    parameter integer C_MEMORY_SIZE =        512,    // Word (not byte), 2のn乗
    parameter integer DATA_BUS_WIDTH =        32        // RAM Data Width
)
(
    input    wire    clk,
    input    wire    rst,
    input    wire    wr_en,
    input    wire    [DATA_BUS_WIDTH-1:0]    din,
    output    wire    full,
    output    wire    almost_full,
    input    wire    rd_en,
    output    wire     [DATA_BUS_WIDTH-1:0]    dout,
    output    wire    empty,
    output    wire    almost_empty
);

    // Beyond Circuts, Constant Function in Verilog 2001を参照しました
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction
    
    reg        [DATA_BUS_WIDTH-1:0]    mem    [0:C_MEMORY_SIZE-1];
    reg        [log2(C_MEMORY_SIZE)-1:0]   mem_waddr = 0;
    reg        [log2(C_MEMORY_SIZE)-1:0]   mem_raddr = 0;
    reg        [log2(C_MEMORY_SIZE)-1:0]    rp = 0;
    reg        [log2(C_MEMORY_SIZE)-1:0]    wp = 0;

    wire    [log2(C_MEMORY_SIZE)-1:0]   plus_1 = 1;
    wire    [log2(C_MEMORY_SIZE)-1:0]   plus_2 = 2;

    wire    almost_full_node;
    wire    almost_empty_node;

    integer i;
    // initialize RAM Data
    initial begin
        for (i=0; i<C_MEMORY_SIZE; i=i+1)
            mem[i] = 0;
    end

    // Write
    always @(posedge clk) begin
        if (rst) begin
            mem_waddr <= 0;
            wp <= 0;
        end else begin
            if (wr_en) begin
                mem_waddr <= mem_waddr + 1;
                wp <= wp + 1;
            end
        end
    end

    always @(posedge clk) begin
         if (wr_en) begin
            mem[mem_waddr] <= din;
        end
    end

    assign full = (wp+plus_1 == rp) ? 1'b1 : 1'b0;
    assign almost_full_node = (wp+plus_2 == rp) ? 1'b1 : 1'b0;
    assign almost_full = full | almost_full_node;

    // Read
    always @(posedge clk) begin
        if (rst) begin
            mem_raddr <= 0;
            rp <= 0;
        end else begin
            if (rd_en) begin
                mem_raddr <= mem_raddr + 1;
                rp <= rp + 1;
            end
        end
    end

    assign dout = mem[mem_raddr];

    assign empty = (wp == rp) ? 1'b1 : 1'b0;
    assign almost_empty_node = (wp == rp+plus_1) ? 1'b1 : 1'b0;
    assign almost_empty = empty | almost_empty_node;
endmodule

`default_nettype wire


インスタンスする際にメモリ容量 C_MEMORY_SIZE はカウンタが回る都合上、2のn乗である必要がある。

次にテストベンチ (sync_fifo_tb.v) を下に貼っておく。

`default_nettype none
`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: marsee
//
// Create Date:   11:52:36 11/08/2013
// Design Name:   sync_fifo
// Module Name:   D:/HDL/FndISEWork/Zynq-7000/ZedBoard/test/sync_fifo/sync_fifo_tb.v
// Project Name:  sync_fifo
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: sync_fifo
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module sync_fifo_tb;

    parameter DELAY = 10;

    // Inputs
    wire clk;
    wire rst;
    reg wr_en;
    reg [31:0] din;
    reg rd_en;

    // Outputs
    wire full;
    wire almost_full;
    wire [31:0] dout;
    wire empty;
    wire almost_empty;

    // Instantiate the Unit Under Test (UUT)
    sync_fifo #(
        .C_MEMORY_SIZE(16),
        .DATA_BUS_WIDTH(32)
    ) uut (
        .clk(clk), 
        .rst(rst), 
        .wr_en(wr_en), 
        .din(din), 
        .full(full), 
        .almost_full(almost_full), 
        .rd_en(rd_en), 
        .dout(dout), 
        .empty(empty), 
        .almost_empty(almost_empty)
    );

    initial begin
        // Initialize Inputs
        wr_en = 0;
        din = 0;
        rd_en = 0;

        // Wait 100 ns for global reset to finish
        #1000;
        
        // Add stimulus here
        fifo_write(32'h11223340, 15);
        fifo_read(15);
        fifo_write(32'h11223340, 4);
        fifo_read(4);    
    end

    // Write Task
    task fifo_write;
        input     [31:0]    din_temp;
        input    [31:0]    wr_cnt;
        integer i;
        begin
            @(posedge clk);
            #DELAY;
            wr_en = 1'b1;
            for (i=0; i<wr_cnt; i=i+1) begin
                din = din_temp;
                @(posedge clk);
                #DELAY;
                din_temp = din_temp + 1;
            end
            wr_en = 1'b0;
        end
    endtask

    // Read Task
    task fifo_read;
        input [31:0] rd_cnt;
        integer i;
        begin
            @(posedge clk);
            #DELAY;
            rd_en = 1'b1;
            for (i=0; i<rd_cnt; i=i+1) begin
                @(posedge clk);
                #DELAY;
            end
            rd_en = 1'b0;
        end
    endtask


    // clk_gen のインスタンス(clk)
    clk_gen #(
        .CLK_PERIOD(100),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) CLKi (
        .clk_out(clk)
    );

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b1),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(rst),
        .init_done()
    );
      
endmodule


module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end
endmodule

`default_nettype wire

  1. 2013年11月09日 04:14 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master Interfaceモジュールの作製2(シミュレーション)

AXI4 Master Interfaceモジュールの作製1(仕様の検討)”の続き。

汎用AXI Master IPを目指して、ユーザー回路を非同期FIFOのインターフェースで接続するAXI4 Master Interfaceモジュールが大体出来た。非同期FIFOを使用しているので、例えばユーザー回路がフルHDのピクセルクロックで動作して、AXIバスが200MHzで動作するということが可能になる。AXI Interconnect のクロックレート変換を使うこともできるが、ここはスマートにクロックドメインを分けることにした。ユーザー回路でも、WriteとReadでクロックを別にしてあるので、異なるクロックを使用することができる。

まずは、ISEのプロジェクトから示す。
axi4_master_inf_2_131108.png

下の示す通りのファイル構成となっている。

・axi4_master_inf_tb.v がテストベンチ
・UUTの axi_master_inf.v がトップファイル(AXI4 Master Interfaceモジュール)
・wadfifo が Writeアドレス転送用の非同期FIFO
・アドレス転送が16個ネストできるので、アドレス転送の情報を保存しておく wadfifo_outs
・wdfifo は Writeデータ転送用の非同期FIFO
・radfifo が Readアドレス転送用の非同期FIFO
・アドレス転送が16個ネストできるので、アドレス転送の情報を保存しておく radfifo_outs
・rdfifo が Readデータ転送用の非同期FIFO
・uut_slave の axi_slave_bfm.v がAXI4 Bus Slave の Bus Functional Model


これをシミュレーションしてみた。まだ、axi_slave_bfm.v がアドレス転送のネストが出来ないため、AXI4 Master Interfaceモジュールの性能は十分にはシミュレーション出来ていない。Writeトランザクションの波形を下に示す。
axi4_master_inf_3_131108.png

Readトランザクションの波形を下に示す。
axi4_master_inf_4_131108.png

次は、axi_slave_BFM.v を変更して、ネストされたアドレス転送を受け付けることにする。現在のBFMはメモリを実装していて実際にメモリにWriteし、またメモリのデータをReadしているが、検証をより易しくするために、Writeデータは書きっぱなし、Readデータは、Writeしたデータに関わらずに、0からインクリメントするようにしようと思う。

最後に、現在のテストベンチを貼っておく。(2013/11/22:修正)

`default_nettype none
`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   03:57:39 11/05/2013
// Design Name:   axi4_master_inf
// Module Name:   D:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/AXI4_bus/axi4_master_inf/axi4_master_inf_tb.v
// Project Name:  axi4_master_inf
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: axi4_master_inf
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module axi4_master_inf_tb;

    parameter DELAY = 10;

    // Inputs
    wire ACLK;
    wire ARESETN;
    wire M_AXI_AWREADY;
    wire M_AXI_WREADY;
    wire [0:0] M_AXI_BID;
    wire [1:0] M_AXI_BRESP;
    wire [0:0] M_AXI_BUSER;
    wire M_AXI_BVALID;
    wire M_AXI_ARREADY;
    wire [0:0] M_AXI_RID;
    wire [63:0] M_AXI_RDATA;
    wire [1:0] M_AXI_RRESP;
    wire M_AXI_RLAST;
    wire [0:0] M_AXI_RUSER;
    wire M_AXI_RVALID;
    wire write_clk;
    wire write_rst;
    reg write_adfifo_wr_ena;
    reg [31:0] write_adfifo_addr;
    reg [7:0] write_adfifo_awlen;
    reg write_fifo_wr_ena;
    reg [63:0] write_fifo_write_data;
    reg [7:0] write_fifo_wstrb;
    wire read_clk;
    wire read_rst;
    reg read_adfifo_wr_ena;
    reg [31:0] read_adfifo_addr;
    reg [7:0] read_adfifo_arlen;
    wire read_fifo_rd_ena;
    reg init_done;

    // Outputs
    wire [0:0] M_AXI_AWID;
    wire [31:0] M_AXI_AWADDR;
    wire [7:0] M_AXI_AWLEN;
    wire [2:0] M_AXI_AWSIZE;
    wire [1:0] M_AXI_AWBURST;
    wire M_AXI_AWLOCK;
    wire [3:0] M_AXI_AWCACHE;
    wire [2:0] M_AXI_AWPROT;
    wire [3:0] M_AXI_AWQOS;
    wire [0:0] M_AXI_AWUSER;
    wire M_AXI_AWVALID;
    wire [63:0] M_AXI_WDATA;
    wire [7:0] M_AXI_WSTRB;
    wire M_AXI_WLAST;
    wire [0:0] M_AXI_WUSER;
    wire M_AXI_WVALID;
    wire M_AXI_BREADY;
    wire [0:0] M_AXI_ARID;
    wire [31:0] M_AXI_ARADDR;
    wire [7:0] M_AXI_ARLEN;
    wire [2:0] M_AXI_ARSIZE;
    wire [1:0] M_AXI_ARBURST;
    wire [1:0] M_AXI_ARLOCK;
    wire [3:0] M_AXI_ARCACHE;
    wire [2:0] M_AXI_ARPROT;
    wire [3:0] M_AXI_ARQOS;
    wire [0:0] M_AXI_ARUSER;
    wire M_AXI_ARVALID;
    wire M_AXI_RREADY;
    wire write_adfifo_full;
    wire write_fifo_full;
    wire wirte_fifo_almost_full;
    wire read_adfifo_full;
    wire [63:0] read_fifo_read_data;
    wire read_fifo_empty_n;
    wire read_fifo_almost_empty_n;
    wire wr_resp_err;

    // Instantiate the Unit Under Test (UUT)
    axi4_master_inf #(
        .C_M_AXI_DATA_WIDTH(64)
    ) uut (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .M_AXI_AWID(M_AXI_AWID),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWLEN(M_AXI_AWLEN),
        .M_AXI_AWSIZE(M_AXI_AWSIZE),
        .M_AXI_AWBURST(M_AXI_AWBURST),
        .M_AXI_AWLOCK(M_AXI_AWLOCK),
        .M_AXI_AWCACHE(M_AXI_AWCACHE),
        .M_AXI_AWPROT(M_AXI_AWPROT),
        .M_AXI_AWQOS(M_AXI_AWQOS),
        .M_AXI_AWUSER(M_AXI_AWUSER),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WLAST(M_AXI_WLAST),
        .M_AXI_WUSER(M_AXI_WUSER),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BID(M_AXI_BID),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BUSER(M_AXI_BUSER),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .M_AXI_ARID(M_AXI_ARID),
        .M_AXI_ARADDR(M_AXI_ARADDR),
        .M_AXI_ARLEN(M_AXI_ARLEN),
        .M_AXI_ARSIZE(M_AXI_ARSIZE),
        .M_AXI_ARBURST(M_AXI_ARBURST),
        .M_AXI_ARLOCK(M_AXI_ARLOCK),
        .M_AXI_ARCACHE(M_AXI_ARCACHE),
        .M_AXI_ARPROT(M_AXI_ARPROT),
        .M_AXI_ARQOS(M_AXI_ARQOS),
        .M_AXI_ARUSER(M_AXI_ARUSER),
        .M_AXI_ARVALID(M_AXI_ARVALID),
        .M_AXI_ARREADY(M_AXI_ARREADY),
        .M_AXI_RID(M_AXI_RID),
        .M_AXI_RDATA(M_AXI_RDATA),
        .M_AXI_RRESP(M_AXI_RRESP),
        .M_AXI_RLAST(M_AXI_RLAST),
        .M_AXI_RUSER(M_AXI_RUSER),
        .M_AXI_RVALID(M_AXI_RVALID),
        .M_AXI_RREADY(M_AXI_RREADY),
        .write_clk(write_clk),
        .write_rst(write_rst),
        .write_adfifo_wr_ena(write_adfifo_wr_ena),
        .write_adfifo_addr(write_adfifo_addr),
        .write_adfifo_awlen(write_adfifo_awlen),
        .write_adfifo_full(write_adfifo_full),
        .write_fifo_wr_ena(write_fifo_wr_ena),
        .write_fifo_write_data(write_fifo_write_data),
        .write_fifo_wstrb(write_fifo_wstrb),
        .write_fifo_full(write_fifo_full),
        .wirte_fifo_almost_full(wirte_fifo_almost_full),
        .read_clk(read_clk),
        .read_rst(read_rst),
        .read_adfifo_wr_ena(read_adfifo_wr_ena),
        .read_adfifo_addr(read_adfifo_addr),
        .read_adfifo_arlen(read_adfifo_arlen),
        .read_adfifo_full(read_adfifo_full),
        .read_fifo_rd_ena(read_fifo_rd_ena),
        .read_fifo_read_data(read_fifo_read_data),
        .read_fifo_empty_n(read_fifo_empty_n),
        .read_fifo_almost_empty_n(read_fifo_almost_empty_n),
        .wr_resp_err(wr_resp_err),
        .init_done(init_done)
    );

    // Write
    initial begin
        // Initialize Inputs
        write_adfifo_wr_ena = 0;
        write_adfifo_addr = 0;
        write_adfifo_awlen = 0;
        write_fifo_wr_ena = 0;
        write_fifo_write_data = 0;
        write_fifo_wstrb = 0;
        init_done = 0;
        // Wait 100 ns for global reset to finish
        #1000;

        // Add stimulus here
        init_done = 1'b1;

        AXI4_Write_Trans_Auto(32'h11220000, 8'd0, 64'h2233445566778890, 8'hf0);
        AXI4_Write_Trans_Auto(32'h12340000, 8'd7, 64'h123456789ABCDEF0, 8'hff);
        AXI4_Write_Trans_Auto(32'h56780000, 8'd15, 64'h1122334455667788, 8'hff);
        AXI4_Write_Addr_Trans(32'h67890000, 8'd31);
        AXI4_Write_Addr_Trans(32'h789A0000, 8'd63);
        AXI4_Write_Data_Trans(64'h33445566778899A0, 8'hff, 8'd31);
        AXI4_Write_Data_Trans(64'h445566778899AAB0, 8'hff, 8'd63);
    end

    // Read
    assign read_fifo_rd_ena = read_fifo_empty_n;
    initial begin
        // Initialize Inputs
        read_adfifo_wr_ena = 0;
        read_adfifo_addr = 0;
        read_adfifo_arlen = 0;

        // Wait 100 ns for global reset to finish
        #1000;

        // Add stimulus here

        AXI4_Read_Trans_Auto(32'h11220000, 8'd0);
        AXI4_Read_Trans_Auto(32'h12340000, 8'd7);
        AXI4_Read_Trans_Auto(32'h56780000, 8'd15);
        AXI4_Read_Trans_Auto(32'h67890000, 8'd127);
    end

    // Write Channel Task
    task AXI4_Write_Trans_Auto;
        input     [31:0]    write_addr;
        input    [7:0]    awlen;            // 転送長-1
        input    [63:0]    start_wdata;    // wdataは1バーストごとに+1される
        input    [7:0]    wstb;
        integer    i;
        begin
            AXI4_Write_Addr_Trans(write_addr, awlen);
            AXI4_Write_Data_Trans(start_wdata, wstb, awlen);
        end
    endtask

    task AXI4_Write_Addr_Trans;
        input     [31:0]    write_addr;
        input    [7:0]    awlen;            // 転送長-1
        begin
            // アドレスと転送長をWrite
            write_adfifo_addr = write_addr;
            write_adfifo_awlen = awlen;

            while(write_adfifo_full) begin    // fullが0になるまでWait
                @(posedge write_clk);    // 次のクロックへ
                #DELAY;
            end

            @(posedge write_clk);    // 次のクロックへ
            #DELAY;
            write_adfifo_wr_ena = 1'b1;

            @(posedge write_clk);    // 次のクロックへ
            #DELAY;
            write_adfifo_wr_ena = 1'b0;
        end
    endtask

    task AXI4_Write_Data_Trans;
        input    [63:0]    start_wdata;    // wdataは1バーストごとに+1される
        input    [7:0]    wstb;
        input    [7:0]    awlen;
        integer    i;
        begin
            // 転送データをWrite、データは+1する
            write_fifo_wstrb = wstb;
            write_fifo_wr_ena = 1'b1;
            for (i=0; i<awlen+1; i=i+1) begin
                while(write_fifo_full) begin    // fullが0になるまでWait
                    @(posedge write_clk);    // 次のクロックへ
                    #DELAY;
                end

                write_fifo_write_data = start_wdata;
                @(posedge write_clk);    // 次のクロックへ
                #DELAY;
                start_wdata = start_wdata + 1;
            end

            write_fifo_wr_ena = 1'b0;
            @(posedge write_clk);    // 次のクロックへ
            #DELAY;
        end
    endtask


    // Read Channel Task
    task AXI4_Read_Trans_Auto;
        input    [31:0]    read_addr;
        input    [7:0]    arlen;            // 転送長-1
        begin
            // アドレスと転送長をWrite
            read_adfifo_addr = read_addr;
            read_adfifo_arlen = arlen;

            while(read_adfifo_full) begin    // fullが0になるまでWait
                @(posedge read_clk);    // 次のクロックへ
                #DELAY;
            end

            @(posedge read_clk);    // 次のクロックへ
            #DELAY;
            read_adfifo_wr_ena = 1'b1;

            @(posedge read_clk);    // 次のクロックへ
            #DELAY;
            read_adfifo_wr_ena = 1'b0;
        end
    endtask

    // clk_gen のインスタンス(ACLK)
    clk_gen #(
        .CLK_PERIOD(50),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(ACLK)
    );

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b0),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(ARESETN),
        .init_done()
    );

    // clk_gen のインスタンス(write_clk, read_clk)
    clk_gen #(
        .CLK_PERIOD(67),    // 6.7nsec, 149.3MHz(本当は148.5MHz)
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) WRITE_CLKi (
        .clk_out(write_clk)
    );
    assign read_clk = write_clk;

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b1),
        .RESET_TIME(1000)    // 100nsec
    ) WRITE_RSTi (
        .reset_out(write_rst),
        .init_done()
    );
    assign read_rst = write_rst;

    // Instantiate the Unit Under Test (UUT_slave)
    axi_slave_bfm # (
        .C_M_AXI_DATA_WIDTH(64),
        .WRITE_RANDOM_WAIT(1),    // Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
        .READ_RANDOM_WAIT(1),    //  Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
        .READ_DATA_IS_INCREMENT(1),    // ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
        .RUNDAM_BVALID_WAIT(1)
    ) uut_slave (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .M_AXI_AWID(M_AXI_AWID),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWLEN(M_AXI_AWLEN),
        .M_AXI_AWSIZE(M_AXI_AWSIZE),
        .M_AXI_AWBURST(M_AXI_AWBURST),
        .M_AXI_AWLOCK({1'b0, M_AXI_AWLOCK}),
        .M_AXI_AWCACHE(M_AXI_AWCACHE),
        .M_AXI_AWPROT(M_AXI_AWPROT),
        .M_AXI_AWQOS(M_AXI_AWQOS),
        .M_AXI_AWUSER(M_AXI_AWUSER),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WLAST(M_AXI_WLAST),
        .M_AXI_WUSER(M_AXI_WUSER),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BID(M_AXI_BID),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BUSER(M_AXI_BUSER),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .M_AXI_ARID(M_AXI_ARID),
        .M_AXI_ARADDR(M_AXI_ARADDR),
        .M_AXI_ARLEN(M_AXI_ARLEN),
        .M_AXI_ARSIZE(M_AXI_ARSIZE),
        .M_AXI_ARBURST(M_AXI_ARBURST),
        .M_AXI_ARLOCK(M_AXI_ARLOCK),
        .M_AXI_ARCACHE(M_AXI_ARCACHE),
        .M_AXI_ARPROT(M_AXI_ARPROT),
        .M_AXI_ARQOS(M_AXI_ARQOS),
        .M_AXI_ARUSER(M_AXI_ARUSER),
        .M_AXI_ARVALID(M_AXI_ARVALID),
        .M_AXI_ARREADY(M_AXI_ARREADY),
        .M_AXI_RID(M_AXI_RID),
        .M_AXI_RDATA(M_AXI_RDATA),
        .M_AXI_RRESP(M_AXI_RRESP),
        .M_AXI_RLAST(M_AXI_RLAST),
        .M_AXI_RUSER(M_AXI_RUSER),
        .M_AXI_RVALID(M_AXI_RVALID),
        .M_AXI_RREADY(M_AXI_RREADY)
    );

endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end
endmodule

`default_nettype wire

  1. 2013年11月08日 04:30 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

FPGAエクストリーム・コンピューティング 第4回で発表します

FPGAエクストリーム・コンピューティング 第4回で、”画像ボケ復元用ニューラルネットワークのハードウェア化”という題で発表します。
ブログでは、新しいツールを試したり、仕事に関連ありそうなプラットフォームを作製したり、興味のあるデータを取得したりしています。お仕事の内容をブログに書くこともありますが、書くのはプラットフォームの内容で本当のお仕事の内容を書くことはありません。今回は、お仕事でやったことを勉強会で発表しようと思います。皆さんからしたら、あまり大した内容じゃないかもしれませんが、もしよろしければ聞きに来て頂いて、お話出来たらと思います。

当日は午前中に、坂東市いわい将門ハーフマラソン大会(と言っても5kmの部ですが)に出てから東京に行きますので、ヘロヘロだったらごめんなさい。
再来週には、つくばマラソン(これも10kmです)も控えているので、頑張りたいと思います。

(追記)
今までやってきたお仕事は、”今まで書いた技術論文”にまとまっています。ニューラルネットワークの話題はありませんが。。。

(2013/11/11:追記)
FPGAXで発表したプレゼン資料を公開しました。
  1. 2013年11月05日 04:26 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

Maker Faire Tokyo 2013 に出展しました

栗元さんのご厚意により、Maker Faire Tokyo 2013に出店することが出来ました。お礼申し上げます。ありがとうございました。Makeも終了しました。簡単にブースを紹介したいと思います。あまり他のブースは見に行っていないので、写真がありません。

栗元さんの展示。Androidの顔認証APIを使用して、ぬいぐるみを2軸のサーボモータで制御して、ぬいぐるみが、自分の顔の方を向くというデモです。特に女の子や子供に大受けでした。羨ましい。。。
Make_2013_2_131104.jpg

私のブース。光るアクリルサインや象嵌アクリルサインを並べました。星のアクリルサインを神輿に付けた時のビデオを流したり、写真を用意すればよかったです。
Make_2013_3_131104.jpg

ぜひ、自分の写真で光るアクリルサインを作ってくださいという方がいたんですが、作製は請け負っていないということで断ってしました。FPGA-CAFEに来て、一緒に作りましょうと言ってあげればよかったです。少し、後悔。。。

7-11でゴムゴムの実の菓子パンを売っていたので、買って食べました。ブルーベリーソースとホイップクリームでした。
Make_2013_4_131104.jpg

3階では、いろいろナイスの展示がありました。
これは、1位の半球形の料理用のボールみたいな椅子です。どうやって座るんでしょうか?
Make_2013_5_131104.jpg

FPGA-CAFEの椅子です。
Make_2013_6_131104.jpg

変わった椅子がいろいろありましたよ。
Make_2013_7_131104.jpg

近くでは室内飛行機のブースがあって、常にいろんな飛行機が飛んでました。ナウシカの虫の羽ばたき飛行機が飛んできたので写真を取らせて頂きました。
Make_2013_8_131104.jpg

Make_2013_9_131104.jpg

FPGAの部屋を見ていただいている方にもお会いできて、嬉しかったです。FPGAはありませんでしたが、よく来て下さいました。見ていただいた方すべてに感謝です。ありがとうございました。
  1. 2013年11月04日 21:57 |
  2. Make出展
  3. | トラックバック:0
  4. | コメント:0

Maker Faire Tokyo 2013 に出展します

11月3日(日)、11月4日(月)に行われる Make Faire Tokyo 2013 に出展します。

展示ゾーンは、日本科学未来館1F 企画展示ゾーン F-06の「栗元憲一&しかじろう」さんのブースに間借りさせてもらいます。間借りさせて頂いて、ありがとうございます。感謝感謝です。。。

展示内容は、FPGAとは全く関係ないですが、FPGAの部屋バージョンの光るアクリルサインと私の実際の顔を光るアクリルサインにしたもの、星の光るアクリルサインを2種類、これは彫り方が違うので、光り方が違います。
acrylic_signs_2_131020.jpg

あと、象嵌アクリルサインを展示します。これは、透明のアクリルを切り取って、他と同じに色アクリルを切り取って入れ替えたもので、いわばパズルみたいなものですね。
acrylic_signs_1_130907.jpg

acrylic_signs_2_131101.jpg

後は、もう1つ実験的なアクリル工作を展示します。

皆さん、Make Faire Tokyo 2013 に来た際には、お寄り下さい。FPGAはないですけど。。。
  1. 2013年11月01日 20:02 |
  2. Make出展
  3. | トラックバック:0
  4. | コメント:0

Sublime Text3 エディタ

長らくNotepad++をVHDLやVerilog HDLを書くときのエディタとして使ってきましたが、自動補完機能がおかしくなりやすいので、どうしようかと思っていました。今日、学生実験で学生さんに Sublime Text 3 を教えてもらったので書いておきます。

Sublime Text 3 はプログラマに人気のプラグインが豊富なカスタマイズできるエディタだそうです。

Sublime Text3をWindowsに入れてみた!初めての導入と簡単なカスタマイズまとめ”を見ながらインストール、カスタマイズをしました。とってもわかりやすいまとめに感謝です。

インストールしているプラグインは、以下の通りです。
{
"installed_packages":
[
"ConvertToUTF8",
"IMESupport",
"SystemVerilog",
"Verilog",
"Verilog Automatic"
]
}

自動補完もあるし、テンプレートも入る(自分でカスタマイズしたいのですが、まだ方法がわかりません)ので便利です。もっと勉強すると便利に使えそうです。
sublime_text3_1_131031.png

・パッケージのインストール方法
パッケージのインストール方法は、Preferences -> Package Control を選択します。
sublime_text3_2_131101.png

ダイアログからInstall Package を選択します。
sublime_text3_3_131101.png

出てきたダイアログで白い部分に検索テキストを入れればパッケージを検索してくれます。
sublime_text3_4_131101.png


・VHDLのシンタックス・ハイライト
VHDLのパッケージは上の、パッケージのインストール方法では出来ませんでした。その方法を書いておきます。
1.github.com/yangsu/sublime-vhdlから、sublime-vhdl-master.zipをダウンロードします。

2.Preferences -> Browse Packages... を選択します。
sublime_text3_5_131101.png

3.出てきたエクスプローラ上で、VHDLフォルダを新規作成します。
sublime_text3_6_131101.png

3.1.でダウンロードした sublime-vhdl-master.zip\sublime-vhdl-master の中身を新規作成したVHDLフォルダにコピーします。
sublime_text3_7_131101.png

4.Sublime Text 3 を再起動します。

これで、VHDLのハイライトもできるようになりました。これで、Notepad++から移行できます。
sublime_text3_8_131101.png

なお、VHDLのパッケージをインストールする方法は、”Syntax highligthing for VHDL”を参考にさせて頂きました。
  1. 2013年11月01日 04:53 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:0