FPGA開発日記

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

AXIルータ生成プログラムの作成(デコーダの記述)

AXIルータを自動生成できるよう、スクリプトを記述している。 今は、入力データに対して、どのようにアドレスデコーダを搭載して、パケットをルーティングするかというところだ。

$regions = Array[Array['START', Array['1011_1111_1100_XXXX_XXXX_XXXX_XXXX_XXXX']],
                 Array['TEXT',  Array['1000_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX']],
                 Array['L1',    Array['0111_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX']],
                 Array['EX',    Array['others']]]

とりあえず、指定されたアドレス領域ならば、その方向へルーティングするべき信号をassertするような生成コードを作った。

github.com

def gen_region_detector(fp, regions)
  regions.each{|region|
    region_name = region[0]
    region_addresses = region[1]
    address_exp = ""
    region_addresses.each{|region_address|
      if region_address == 'others' then
        regions.each {|not_region|
          address_exp = gen_and(address_exp, "~" + "is_region_" + not_region[0])
        }
        break
      else
        start = 31
        index = start
        bit_region_idx = 0
        bit_region = ""
        region_address.each_char{|bit|
          if bit == '_' then
            next
          elsif bit == '1' or bit == '0' then
            index=index-1
            bit_region[bit_region_idx] = bit
            bit_region_idx = bit_region_idx + 1
          elsif index != start then
            address_exp = gen_or(address_exp,
                                 sprintf(gen_signal_bitwidth(region_name, start, index)) + " == " + sprintf("2'b%s", bit_region))
            start=index
            bit_region_idx = 0
          else
            start = start - 1
            index = index - 1
          end
        }
      end
    }
    fp.printf(connect_assign("is_region_" + region_name, address_exp))
  }
end

一つ一つアドレス情報をデコードして、ビットインデックスを作成していく。Xに到達したら、それより前のビット情報で比較コードを生成することを繰替えす。 これで、以下のようなコードが生成されるようになる。othersを使うと、それまでに作成した信号がどれもassertされないときに有効になる。

assign is_region_START = START[31:19] == 2'b101111111100;
assign is_region_TEXT = TEXT[31:27] == 2'b1000;
assign is_region_L1 = L1[31:27] == 2'b0111;
assign is_region_EX = (((~is_region_START) &
(~is_region_TEXT)) &
(~is_region_L1)) &
(~is_region_EX);

ちょっと体裁が不細工だが、自動生成だし、まずはしようがない。これを使って、いよいよパケットのルーティングと、次はアービトレーションをできるようにしていこう。