에피소드 III: 레지스터 파일

stackoverflow 답변에 따라, 레지스터 파일은 클록 틱마다 레지스터 값 두 개를 읽고, 필요하면 값 하나를 씁니다. 또한 RISC-V 명세를 보면 특수 레지스터 zero가 있다는 것을 알 수 있습니다. 이 레지스터는 읽으면 항상 0을 반환하고, 여기에 쓰는 값은 무시합니다. 다음은 레지스터 파일의 단순화된 버전입니다:

module NrvRegisterFile(
  input         clk, 
  input [31:0]      in,        // Data for write back register
  input [4:0]       inRegId,   // Register to write back to
  input         inEn,      // Enable register write back
  input [4:0]       outRegId1, // Register number for out1
  input [4:0]       outRegId2, // Register number for out2
  output reg [31:0] out1,      // Data out 1, available one clock after outRegId1 is set
  output reg [31:0] out2       // Data out 2, available one clock after outRegId2 is set
);
   reg [31:0]  bank1 [31:0];
   reg [31:0]  bank2 [31:0];
   always @(posedge clk) begin
      if (inEn) begin
     if(inRegId != 0) begin 
        bank1[inRegId] <= in;
        bank2[inRegId] <= in;
     end      
      end 
      out1 <= bank1[outRegId1];
      out2 <= bank2[outRegId2];
   end 
endmodule

레지스터 두 개를 읽어야 합니다(예를 들어 ALU 연산의 두 피연산자). 보통은 두 사이클이 필요하지만, 레지스터 파일 전체를 복제하면 한 사이클에 읽을 수 있습니다(bank1과 bank2가 있는 이유가 이것입니다).

실제로 femtorv32.v를 살펴보면 조금 다릅니다. Claire Wolf의 PicoRV32 소스에서 가져온, 레지스터 zero를 더 영리하게 처리하는 방식을 사용합니다. 바로 레지스터 인덱스를 반전하는 방식입니다.

다음