FPGA開発日記

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

オープンソース・アウトオブオーダCPU NaxRiscvを概観する (13. PCPluginをSystemVerilogに変換する)

NaxRiscvの実装を解析しながら、SystemVerilog化することで理解を深めていこうと思う。

まずはPCPluginから。このモジュールの役目は、PCの保持とアップデート、各種ハザードに応じてPCを更新することだ。

module NaxRiscv_PcPlugin
  (
   input logic  i_clk,
   input logic  i_reset_n,

   PcPlugin_if.manager        pcplugin_if, // output                                                                                                                                                                                                                                                                                                           
   );

基本的には、PCを送出すると更新することになる。

assign output_fire  = pcplugin_if.valid && pcplugin_if.ready;
always_comb begin
  w_pc = r_pc + _zz_pc;
  if(w_jump_pcload_valid) begin
    w_pc = w_jump_pcload_pc;
  end

  if (r_pc_inc) begin
    w_pc[2 : 2] = 1'b0;
  end
  w_pc[1:0] = 2'b00;
end

always_ff ...
    if(output_fire) begin
      r_correction <= 1'b0;
    end else if(w_correction) begin
      r_correction <= 1'b1;
    end

    if(!pcplugin_if.valid && pcplugin_if.ready) begin
      r_pc_inc <= 1'b0;
    end else if(output_fire) begin
      r_pc_inc <= 1'b1;
    end else if(w_correction || w_pcPropagate) begin
      r_pc_inc <= 1'b0;
    end

各種ハザード通知に応じて、更新するPCを変えている。

always_comb begin
  if (PrivilegedPlugin_setup_jump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = PrivilegedPlugin_setup_jump_payload_pc;
  end else if (CommitPlugin_setup_jump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = CommitPlugin_setup_jump_payload_pc;
  end else if (DecoderPredictionPlugin_setup_decodeJump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = DecoderPredictionPlugin_setup_decodeJump_payload_pc;
  end else if (AlignerPlugin_setup_sequenceJump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = AlignerPlugin_setup_sequenceJump_payload_pc;
  end else if (FetchCachePlugin_setup_redoJump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = FetchCachePlugin_setup_redoJump_payload_pc;
  end else if (BtbPlugin_setup_btbJump_valid) begin
    w_jump_pcload_valid = 1'b1;
    w_jump_pcload_pc    = BtbPlugin_setup_btbJump_payload_pc;
  end else begin
    w_jump_pcload_valid = 1'b0;
    w_jump_pcload_pc    = 40'h0;
  end
end // always_comb                                                                                                                                                                                                                                                                                                                                             

InitCounterは単純なカウンタだが、これはここに配置する意味はあるんだろうか?128サイクル待っているようなカウンタだ。

reg        [6:0]    r_init_counter;
wire                w_init_booted;

assign w_init_booted = r_init_counter[6];

always_ff @ (posedge i_clk, negedge i_reset_n) begin
  if (!i_reset_n) begin
    r_init_counter <= 7'h00;
  end else begin
    r_init_counter <= r_init_counter + ~w_init_booted;
  end
end