FPGA開発日記

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

順不同に格納されたエントリの順番を保持するAge Matrix回路について (SystemVerilogで書いてみる)

Age Matrixの続き。理解のために実際に自分でも書いてみることにした。

モジュールとしては SIZEエントリを保持するバッファを作ってみた。

  • push
    • Valid
    • Pushする場所を示すインデックス(OH)
    • Pushするデータ
  • pop
    • Valid
    • Popする場所を示すインデックス(OH)
 logic [SIZE-1: 0]                 r_entry_valid;   // エントリが有効であることを示す
 logic [31: 0]                     r_entry [SIZE];   // エントリの値
 logic [SIZE-1:0]                  r_age_matrix[SIZE];   // Age Matrixのレジスタ
 logic [SIZE-1: 0]                 w_age_matrix_or;   // Age MatrixのOR値
 logic [SIZE-1: 0]                 w_grant;  // Validに対してGrantを取っているポート(OH)

まずAge Matrixの論理だが、

  • Push時:Pushする自分のエントリのAge Matrixに対して、これまでに格納されているエントリの位置を示すビットのORを格納する。
  • Pop時:すべてのエントリのAge Matrixに対して自分の位置をしめすビットを0に落とす

これを記述したのが以下となる(詳細に検証していないので細かいところで間違ってるかも)。

 bit_or #(.WIDTH(SIZE), .WORDS(SIZE)) age_matrix_or (.i_data(r_age_matrix), .o_selected(w_age_matrix_or));

 generate for (genvar i = 0; i < SIZE; i++) begin : e_loop
   logic [SIZE-1: 0] w_age_matrix_in;
   assign w_age_matrix_in = {SIZE{i_push & i_push_idx_oh[i]}} & (w_age_matrix_or | (1 << i)) |
                            ~({SIZE{i_pop}} & i_pop_idx_oh) & r_age_matrix[i];
   always_ff @ (posedge i_clk, negedge i_reset_n) begin
     if (!i_reset_n) begin
       r_age_matrix[i] <= {SIZE{1'b0}};
     end else begin
       r_age_matrix[i] <= (i_push & i_push_idx_oh[i] | i_pop) ? w_age_matrix_in : r_age_matrix[i];
     end
   end

i_push時にはi_push_idx_oh[i]に対して(つまり自分)のみw_age_matrix_orの値と自分を示すビット(1 << i)をORして格納する。 i_pop時には、すべてのビットに対してr_age_matrix[i]から自分を示すビットを消して格納する。

grant信号は、とりあえず自分以外のビットが立っていればGrantしないという論理にする。

 generate for (genvar i = 0; i < SIZE; i++) begin : e_loop
   assign w_grant[i] = r_entry_valid[i] & ~|(r_age_matrix[i] & ~(1 << i));
 end
 endgenerate

とりあえずテストベンチを作ってシミュレーションしてみる。

f:id:msyksphinz:20210328000759p:plain

なんとなく上手く行っている気がする。