-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregfile.v
65 lines (57 loc) · 1.72 KB
/
regfile.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
This is an Internal-Forwarding Register File(IFRF). It has 3 ports,
two read-only for rs1 and rs2, and one write-only for rd.
x0 always reads 0, and have no effect writing (though it is actually
written into RF, the value can never be read)
During writeback, if rd address equals to rs1/rs2 address, the source
register outputs the latest value.
This IFRF is implemented using an array of registers, consuming 32x32=1024
registers instead of the scarcer BRAMs. More importantly, register access
is finished in a single clock, allowing the pipeline to be as short as
two stages.
*/
module regfile(
input wire clk, input wire resetb,
input wire [4:0] a_rs1,
output reg [31:0] d_rs1,
input wire [4:0] a_rs2,
output reg [31:0] d_rs2,
input wire [4:0] a_rd,
input wire [31:0] d_rd,
input wire we_rd
);
// 32x32 registers
reg [31:0] data [0:31] /*verilator public*/;
// Temporary variable
integer i;
always @ (posedge clk) begin : MAIN_CLK_PROCESS
if (!resetb) begin
// Registers do not initialize
for (i = 0; i < 32; i = i + 1) begin
data[i] <= 32'bX;
end
end
else if (clk) begin
// Write back
if (we_rd) begin
data[a_rd] <= d_rd;
end
end
end // block: MAIN_CLK_PROCESS
always @ (*) begin : COMBINATIONAL_PROCESS
// Forwarding rs1
if (a_rs1 == 5'b0)
d_rs1 = 32'b0;
else if (we_rd && a_rd != 5'b0 && a_rs1 == a_rd)
d_rs1 = d_rd;
else
d_rs1 = data[a_rs1];
// Forwarding rs2
if (a_rs2 == 5'b0)
d_rs2 = 32'b0;
else if (we_rd && a_rd != 5'b0 && a_rs2 == a_rd)
d_rs2 = d_rd;
else
d_rs2 = data[a_rs2];
end
endmodule // regfile