에피소드 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를 더 영리하게 처리하는
방식을 사용합니다. 바로 레지스터 인덱스를 반전하는 방식입니다.