やかんです。

ディジタル回路、コンピュータアーキテクチャ、ハードウェア設計論などを受講する中で、なんとなーく何から始めればいいか分かりつつある気がします。

東大生やかんのブログ
やかん

気のせいか?

シングルサイクルプロセッサの完成を目標にしてみる。

まずは、シングルサイクルプロセッサを目指そうと思います。多分、これが定石なんじゃないかなって思ってますがどうなんでしょうか。

そして、講義においてはデータ転送命令など本格的?な内容ももちろん扱われますが、とりあえずADDとSUBだけに対応したものを作ってみるのはどうだろうか、と思っています。

実際に書いてみる。

GPT-4の助けも借りつつ、書いてみます。まずはモジュール。

module decoder(
  input [31:0] instruction,
  output reg[4:0] rs1,
  output reg[4:0] rs2,
  output reg[4:0] rd,
  output reg [6:0] opcode,
  output reg[2:0] funct3,
  output reg[6:0] funct7,
  output reg add,
  output reg sub
);
  always @(instruction) begin // instructionの値が変わるたびに実行される
    opcode = instruction[6:0];
    rs1 = instruction[19:15];
    rs2 = instruction[24:20];
    rd = instruction[11:7];
    funct3 = instruction[14:12];
    funct7 = instruction[31:25];

    add = 0;
    sub = 0;

    if(opcode == 7'b0110011) begin
      case (funct3)
      3'b000: begin
        if(funct7 == 7'b0000000)
          add = 1;
        else if(funct7 == 7'b0100000)
          sub = 1;
      end
      endcase
    end
  end
endmodule

うん。結構理解できるぞ!命令セットは講義で扱われたものではなく、GPT-4提供のものを使用しています。

次に、テストベンチ。

module decoder_tb;
  reg[31:0] instruction;

  wire[4:0] rs1;
  wire[4:0] rs2;
  wire[4:0] rd;
  wire[6:0] opcode;
  wire[2:0] funct3;
  wire[6:0] funct7;
  wire add;
  wire sub;

  decoder uut (
    .instruction(instruction),
    .rs1(rs1),
    .rs2(rs2),
    .rd(rd),
    .opcode(opcode),
    .funct3(funct3),
    .funct7(funct7),
    .add(add),
    .sub(sub)
  );

  initial begin
    instruction = 32'b0000000_00011_00010_000_00101_0110011;
    #10;

    $display("rs1=%d, rs2=%d, rd=%d, opcode=%d, funct3=%d, funct7=%d, add=%d, sub=%d",
      rs1, rs2, rd, opcode, funct3, funct7, add, sub);

    instruction = 32'b0100000_00101_00100_000_01010_0110011;
    #10;

    $display("rs1=%d, rs2=%d, rd=%d, opcode=%d, funct3=%d, funct7=%d, add=%d, sub=%d",
      rs1, rs2, rd, opcode, funct3, funct7, add, sub);

    $finish;
  end
endmodule

で、$displayによる出力がこちら。

$ vvp decoder_tb.vvp 

rs1= 2, rs2= 3, rd= 5, opcode= 51, funct3=0, funct7=  0, add=1, sub=0
rs1= 4, rs2= 5, rd=10, opcode= 51, funct3=0, funct7= 32, add=0, sub=1
decoder_tb.v:38: $finish called at 20 (1s)

おお!良さそう!

あとはこれを、講義で扱われたRISC-Vの命令セットに書き換えて、ADDとSUB以外にも拡張していけば良いのではないだろうか。

そのほか気づきメモ

  • シングルサイクルプロセッサは、パイプラインとかの工夫が施される前のプロセッサの状態だと思っている。
  • プログラムカウンタとかクロックは、同期を実現するためのものだ。クロックの立ち上がりで同期する。
    • 同期を実現することで、安定した処理を実現しているという理解をしている。

今回のまとめ。

なんとなく、何をすればいいか分かりつつある。ここから徐々に、対応する命令セットを増やしていけば良いのではないだろうか。

結構スッキリ感があっていい感じですが、今回はこれにて終了。最後までお読みいただき、ありがとうございます。