forked from openhwgroup/cv32e40p
/
riscv_register_file.sv
189 lines (158 loc) · 6.87 KB
/
riscv_register_file.sv
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// Engineer: Francesco Conti - f.conti@unibo.it //
// //
// Additional contributions by: //
// Michael Gautschi - gautschi@iis.ee.ethz.ch //
// //
// Design Name: RISC-V register file //
// Project Name: RI5CY //
// Language: SystemVerilog //
// //
// Description: Register file with 31x 32 bit wide registers. Register 0 //
// is fixed to 0. This register file is based on flip-flops. //
// Also supports the fp-register file now if FPU=1 //
// //
////////////////////////////////////////////////////////////////////////////////
module riscv_register_file
#(
parameter ADDR_WIDTH = 5,
parameter DATA_WIDTH = 32,
parameter FPU = 0
)
(
// Clock and Reset
input logic clk,
input logic rst_n,
input logic test_en_i,
input logic fregfile_disable_i,
//Read port R1
input logic [ADDR_WIDTH-1:0] raddr_a_i,
output logic [DATA_WIDTH-1:0] rdata_a_o,
//Read port R2
input logic [ADDR_WIDTH-1:0] raddr_b_i,
output logic [DATA_WIDTH-1:0] rdata_b_o,
//Read port R3
input logic [ADDR_WIDTH-1:0] raddr_c_i,
output logic [DATA_WIDTH-1:0] rdata_c_o,
// Write port W1
input logic [ADDR_WIDTH-1:0] waddr_a_i,
input logic [DATA_WIDTH-1:0] wdata_a_i,
input logic we_a_i,
// Write port W2
input logic [ADDR_WIDTH-1:0] waddr_b_i,
input logic [DATA_WIDTH-1:0] wdata_b_i,
input logic we_b_i
);
// number of integer registers
localparam NUM_WORDS = 2**(ADDR_WIDTH-1);
// number of floating point registers
localparam NUM_FP_WORDS = 2**(ADDR_WIDTH-1);
localparam NUM_TOT_WORDS = FPU ? NUM_WORDS + NUM_FP_WORDS : NUM_WORDS;
// integer register file
logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] mem;
// fp register file
logic [NUM_FP_WORDS-1:0][DATA_WIDTH-1:0] mem_fp;
// mask bit for fpregfile selection (top bit of address)
logic fregfile_ena;
// masked write addresses
logic [ADDR_WIDTH-1:0] waddr_a;
logic [ADDR_WIDTH-1:0] waddr_b;
// write enable signals for all registers
logic [NUM_TOT_WORDS-1:0] we_a_dec;
logic [NUM_TOT_WORDS-1:0] we_b_dec;
//-----------------------------------------------------------------------------
//-- FPU Register file enable:
//-- Taken from Cluster Config Reg if FPU reg file exists, or always enabled (safe default)
//-----------------------------------------------------------------------------
assign fregfile_ena = FPU ? ~fregfile_disable_i : '1;
//-----------------------------------------------------------------------------
//-- READ : Read address decoder RAD
//-----------------------------------------------------------------------------
if (FPU == 1) begin
assign rdata_a_o = (fregfile_ena & raddr_a_i[5]) ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]];
assign rdata_b_o = (fregfile_ena & raddr_b_i[5]) ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]];
assign rdata_c_o = (fregfile_ena & raddr_c_i[5]) ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]];
end else begin
assign rdata_a_o = mem[raddr_a_i[4:0]];
assign rdata_b_o = mem[raddr_b_i[4:0]];
assign rdata_c_o = mem[raddr_c_i[4:0]];
end
//-----------------------------------------------------------------------------
//-- WRITE : Write Address Decoder (WAD), combinatorial process
//-----------------------------------------------------------------------------
// Mask top bit of write address to disable fp regfile
assign waddr_a = {(fregfile_ena & waddr_a_i[5]), waddr_a_i[4:0]};
assign waddr_b = {(fregfile_ena & waddr_b_i[5]), waddr_b_i[4:0]};
always_comb
begin : we_a_decoder
for (int i = 0; i < NUM_TOT_WORDS; i++) begin
if (waddr_a == i)
we_a_dec[i] = we_a_i;
else
we_a_dec[i] = 1'b0;
end
end
always_comb
begin : we_b_decoder
for (int i=0; i<NUM_TOT_WORDS; i++) begin
if (waddr_b == i)
we_b_dec[i] = we_b_i;
else
we_b_dec[i] = 1'b0;
end
end
genvar i,l;
generate
//-----------------------------------------------------------------------------
//-- WRITE : Write operation
//-----------------------------------------------------------------------------
// R0 is nil
always_ff @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
// R0 is nil
mem[0] <= 32'b0;
end else begin
// R0 is nil
mem[0] <= 32'b0;
end
end
// loop from 1 to NUM_WORDS-1 as R0 is nil
for (i = 1; i < NUM_WORDS; i++)
begin : rf_gen
always_ff @(posedge clk, negedge rst_n)
begin : register_write_behavioral
if (rst_n==1'b0) begin
mem[i] <= 32'b0;
end else begin
if(we_b_dec[i] == 1'b1)
mem[i] <= wdata_b_i;
else if(we_a_dec[i] == 1'b1)
mem[i] <= wdata_a_i;
end
end
end
if (FPU == 1) begin
// Floating point registers
for(l = 0; l < NUM_FP_WORDS; l++) begin
always_ff @(posedge clk, negedge rst_n)
begin : fp_regs
if (rst_n==1'b0)
mem_fp[l] <= '0;
else if(we_b_dec[l+NUM_WORDS] == 1'b1)
mem_fp[l] <= wdata_b_i;
else if(we_a_dec[l+NUM_WORDS] == 1'b1)
mem_fp[l] <= wdata_a_i;
end
end
end
endgenerate
endmodule