FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

cocotbを試す(3. AXIのモデルを繋げてみる)

github.com

cocotbでAXIの接続をシミュレーションしてみる。まずはAXIのランダム応答のモデルを作ってみる。超適当だけど、ARチャネルとRチャネルのモデルがランダム時間で応答するようにして、それをマスターが正しく受けとることができていれば成功とすれば良い。

    always @ (posedge AXI_CLK) begin
        if (AXI_RESET == 1'b1) begin
            SARREADY <= 1'b0;
        end else begin
            if (SARVALID) begin
                for (rand_ar = 0; rand_ar < ($random % 10); rand_ar = rand_ar + 1) begin
                    @(posedge AXI_CLK);
                end
                SARREADY <= 1'b1;
                ar_rcv_cnt = ar_rcv_cnt + 1;
                @(posedge AXI_CLK);
                SARREADY <= 1'b0;
            end
        end // else: !if(AXI_RESET == 1'b1)
    end // always @ (posedge AXI_CLK)


    always @ (posedge AXI_CLK) begin
        if (AXI_RESET == 1'b1) begin
            SRVALID <= 1'b0;
        end else begin
            if (r_rcv_cnt != ar_rcv_cnt) begin
                for (rand_r = 0; rand_r < ($random % 10); rand_r = rand_r + 1) begin
                    @(posedge AXI_CLK);
                end
                SRVALID <= 1'b1;
                while (SRREADY != 1'b1) begin
                    @(posedge AXI_CLK);
                end
                for (burst_i = 0; burst_i < 4; burst_i = burst_i + 1) begin
                    SRDATA[ 31: 0] <= $random;
                    SRDATA[ 63:32] <= $random;
                    SRDATA[ 95:64] <= $random;
                    SRDATA[127:96] <= $random;
                    @(posedge AXI_CLK);
                end
                SRVALID <= 1'b0;
                r_rcv_cnt = r_rcv_cnt + 1;
            end // if (r_rcv_cnt != ar_rcv_cnt)
        end // else: !if(AXI_RESET == 1'b1)
    end // always @ (posedge AXI_CLK)

cocotbのテストパタンとしては以下のように記述してみた。MARVALIDが立ち上がるか、適当な時間までにMARREADYが帰ってくるか。 その後適当な時間までにMRVALIDが帰ってくるかもチェックしなければならない。

    counter = 0
    while (int(dut.IF_MARVALID) == 0 and counter < MAX_WAIT):
        counter = counter + 1;
        yield Timer(clock_period)
        dut.log.info("counter=%d" % counter)

    if counter == 100:
        raise TestFailure ("IF_MARVALID is not assert")
    elif int(dut.IF_MARVALID) != 1:
        raise TestFailure ("After 2-cycle later, IF_MARVALID is not asserted, IF_MARVALID=%d" % dut.IF_MARVALID)
    else:
        dut.log.info("Ok!")

    counter = 0
    while (int(dut.IF_MARREADY) == 0 and counter < MAX_WAIT):
        counter = counter + 1;
        yield Timer(clock_period)


    if counter == MAX_WAIT:
        yield Timer(1000)
        raise TestFailure ("After IF_MARREADY is not responded")
    elif int(dut.IF_MARREADY) == 1 and int(dut.IF_MARVALID) == 1:
        dut.log.info("Ok!")
    else:
        yield Timer(1000)
        raise TestFailure ("After IF_MARVALID=%d and IF_MARREADY=%d should be both valid" % (dut.IF_MARVALID, dut.IF_MARREADY))

パタンが乱雑になってきたので、関数化して整理するかな。