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
とりあえずテストベンチを作ってシミュレーションしてみる。
なんとなく上手く行っている気がする。