FC2カウンター FPGAの部屋 AXI VDMAのレジスタ設定用AXI Lite Master IPの作製2(シミュレーション)
FC2ブログ

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

FPGAの部屋

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

AXI VDMAのレジスタ設定用AXI Lite Master IPの作製2(シミュレーション)

AXI VDMAのレジスタ設定用AXI Lite Master IPの作製1(仕様の検討)”の続き。

AXI VDMAのレジスタを設定するコントローラのVerilog HDLコードとAXI4 Lite Master用AXI4 Lite Slave BFM(簡易版だけど)を作製できたので、シミュレーションを行った。
下図にシミュレーション結果を示す。
AXI_Lite_Master_3_130620.png

上の図では、AXI VDMAのレジスタを設定するコントローラ (reg_set_axi_lite_master.v) で、AXI VDMAのアドレスと設定値を保存しておくテキストファイル vdma_reg_set.txt の値を使用して、AXI4 Lite Masterアクセスを行なっている。下に、vdma_reg_set.txt の一部を示す。この後は全て0で、全部合計で256個ある。

00000010
12345678
00000020
11223344
00000030
55667788
ffffffff


vdma_reg_set.txt のフォーマットは1番目がアドレス、2番めが設定値となる。奇数番目がアドレス、偶数番目が設定値となる。そして、アドレスに”ffffffff”が現れた時に終了となる。

MicroBlaze があるのに、どうしてこのIPを作ったかというと、MicroBlazeでVDMAなどのレジスタを設定するとシミュレーションをするのに、SDKを立ちあげてソフトウェアを作る必要があるので面倒だ。レジスタを少し設定するだけだったら、すべてISimですることができる今回のレジスタを設定するコントローラIPを作ったほうが面倒が少ないと思ったからだ。設定アドレス、設定データのセットを作るのが面倒だったら、それを生成するスクリプトを作れば良いと思う。このIPは、主にシミュレーションに使用する。簡単な設定で値が固定されている場合は実機で使用しても良いと思う。
実機で頻繁に設定値を変える必要がある時は、プロセッサを使用する。そうすれば、FPGAを再インプリメントすることなしに、設定値を短時間で変更することができる。
下に、reg_set_axi_lite_master.v のコードを示す。

///////////////////////////////////////////////////////////////////////////////
//
// AXI4/Lite Master
//
////////////////////////////////////////////////////////////////////////////
//
// Structure:
//   reg_set_axi_lite_master
//
////////////////////////////////////////////////////////////////////////////

`default_nettype none

module reg_set_axi_lite_master # (
    parameter integer C_M_AXI_ADDR_WIDTH = 32,
    parameter integer C_M_AXI_DATA_WIDTH = 32
)(
    // System Signals
    input wire M_AXI_ACLK,
    input wire M_AXI_ARESETN,

    // Master Interface Write Address
    output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR,
    output wire [3-1:0] M_AXI_AWPROT,
    output wire M_AXI_AWVALID,
    input wire M_AXI_AWREADY,

    // Master Interface Write Data
    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_WVALID,
    input wire M_AXI_WREADY,

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

    // Master Interface Read Address
    output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR,
    output wire [3-1:0] M_AXI_ARPROT,
    output wire M_AXI_ARVALID,
    input wire M_AXI_ARREADY,

    // Master Interface Read Data 
    input wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA,
    input wire [2-1:0] M_AXI_RRESP,
    input wire M_AXI_RVALID,
    output wire M_AXI_RREADY,
    
    input    wire    init_done
);

    reg        [31:0] rom [0:255];
    reg        [31:0] rom_dout;
    
    initial begin
        $readmemh("vdma_reg_set.txt", rom, 0, 255);
    end
    
    reg        reset_1b, reset;
    reg     [31:0]    reg_addr;
    reg        [31:0]    reg_data;
    reg     [7:0]    rom_addr;
    reg        awvalid;
    reg        wvalid;
    reg        bready;

    localparam    RESP_OKAY =        2'b00,
                RESP_EXOKAY =    2'b01,
                RESP_SLVERR =    2'b10,
                RESP_DECERR =    2'b11;
    
    localparam    IDLE_RRSM =                3'b000,
                ADDRESS_READ =            3'b001,
                DATA_READ =                3'b011,
                REG_SET_DATA_VALID =    3'b010,
                END_RRSM =                3'b110;
    reg        [2:0]    rrsm_cs;
    
    localparam    IDLE_ADDR =            2'b00,
                AWVALID_ASSERT =    2'b01,
                AWVALID_HOLD_OFF =    2'b11;
    reg        [1:0]    addr_cs;
    
    localparam    IDLE_DATA =            2'b00,
                WVALID_ASSERT =        2'b01,
                WVALID_HOLD_OFF =    2'b11;
    reg        [1:0]    data_cs;
    
    localparam    IDLE_RESP =        1'b0,
                BREADY_ASSERT =    1'b1;
    reg        resp_cs;
    
    reg        reg_data_valid;
    reg        rom_read_done;
    
    // Read is not implement
    assign M_AXI_ARADDR = 0;
    assign M_AXI_ARPROT = 3'd0;
    assign M_AXI_ARVALID = 1'b0;
    assign M_AXI_RDATA = 0;
    assign M_AXI_RREADY = 1'b1;
    assign M_AXI_WSTRB = 4'b1111;
    assign M_AXI_AWPROT = 3'b000;
    
    // reset
    always @(posedge M_AXI_ACLK) begin
        reset_1b <= ~M_AXI_ARESETN | ~init_done;
        reset <= reset_1b;
    end
    
    // instantiaton of rom
    always @(posedge M_AXI_ACLK) begin
        rom_dout <= rom[rom_addr];
    end
    
    // rom read State Machine
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            rrsm_cs <= IDLE_RRSM;
            reg_data_valid <= 1'b0;
        end else begin
            case (rrsm_cs) 
                IDLE_RRSM : 
                    rrsm_cs <= ADDRESS_READ;
                ADDRESS_READ :
                    rrsm_cs <= DATA_READ;
                DATA_READ : begin
                    if (rom_dout == 32'hFFFF_FFFF) begin // end
                        rrsm_cs <= END_RRSM;
                        reg_data_valid <= 1'b0;
                    end else begin
                        rrsm_cs <= REG_SET_DATA_VALID;
                        reg_data_valid <= 1'b1;
                    end
                end
                REG_SET_DATA_VALID : begin
                    if (rom_read_done) begin
                        rrsm_cs <= ADDRESS_READ;
                        reg_data_valid <= 1'b0;
                    end
                end
                END_RRSM :
                    rrsm_cs <= END_RRSM;
            endcase
        end
    end
    
    // rom_addr
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            rom_addr <= 8'd0;
        end else begin
            if (rrsm_cs == ADDRESS_READ) // Data
                rom_addr <= rom_addr + 8'd1;
            else if (rrsm_cs == REG_SET_DATA_VALID && rom_read_done) // Address
                rom_addr <= rom_addr + 8'd1;
        end
    end
    
    // AXI4 Lite Master Address
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            reg_addr <= 32'd0;
        end else begin
            if (rrsm_cs == DATA_READ)
                reg_addr <= rom_dout;
        end
    end
    assign M_AXI_AWADDR = reg_addr;
    
    // AXI4 Lite Master WDATA
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            reg_data <= 32'd0;
        end else begin
            if (rrsm_cs == REG_SET_DATA_VALID)
                reg_data <= rom_dout;
        end
    end
    assign M_AXI_WDATA = reg_data;
    
    // AXI Lite Master Address State Machine
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            addr_cs <= IDLE_ADDR;
            awvalid <= 1'b0;
        end else begin
            case (addr_cs)
                IDLE_ADDR :
                    if (rrsm_cs == REG_SET_DATA_VALID) begin
                        addr_cs <= AWVALID_ASSERT;
                        awvalid <= 1'b1;
                    end
                AWVALID_ASSERT :
                    if (M_AXI_AWREADY) begin
                        addr_cs <= AWVALID_HOLD_OFF;
                        awvalid <= 1'b0;
                    end
                AWVALID_HOLD_OFF :
                    if (rrsm_cs != REG_SET_DATA_VALID)
                        addr_cs <= IDLE_ADDR;
            endcase
        end
    end
    assign M_AXI_AWVALID = awvalid;
    
    // AXI Lite Master Data State Machine
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            data_cs <= IDLE_DATA;
            wvalid <= 1'b0;
            rom_read_done <= 1'b0;
        end else begin
            case (data_cs)
                IDLE_DATA : begin
                    rom_read_done <= 1'b0;
                    if (rrsm_cs == REG_SET_DATA_VALID) begin
                        data_cs <= WVALID_ASSERT;
                        wvalid <= 1'b1;
                    end
                end
                WVALID_ASSERT :
                    if (M_AXI_WREADY) begin
                        wvalid <= 1'b0;
                        rom_read_done <= 1'b1;
                        data_cs <= WVALID_HOLD_OFF;
                    end
                WVALID_HOLD_OFF : begin
                    rom_read_done <= 1'b0;
                    if (addr_cs == AWVALID_HOLD_OFF)
                        data_cs <= IDLE_DATA;
                end
            endcase
        end
    end
    assign M_AXI_WVALID = wvalid;
    
    // bready State Machine
    always @(posedge M_AXI_ACLK) begin
        if (reset) begin
            resp_cs <= IDLE_RESP;
            bready <= 1'b0;
        end else begin
            case (resp_cs)
                IDLE_RESP :
                    if (M_AXI_WREADY && data_cs == WVALID_ASSERT) begin
                        resp_cs <= BREADY_ASSERT;
                        bready <= 1'b1;
                    end
                BREADY_ASSERT :
                    if (M_AXI_BVALID) begin
                        resp_cs <= IDLE_RESP;
                        bready <= 1'b0;
                    end
            endcase
        end
    end
    assign M_AXI_BREADY = bready;
    
endmodule

`default_nettype none

  1. 2013年06月20日 05:47 |
  2. AXI Lite Master IPコアの作製
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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