OpenCores
URL https://opencores.org/ocsvn/forwardcom/forwardcom/trunk

Subversion Repositories forwardcom

[/] [forwardcom/] [trunk/] [register_read.sv] - Blame information for rev 15

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 Agner
//////////////////////////////////////////////////////////////////////////////////
2
// Engineer: Agner Fog
3
//
4
// Create Date: 2020-06-01
5
// Last modified: 2021-02-16
6
// Module Name: Register read
7
// Project Name: ForwardCom soft core
8
// Target Devices: Artix 7
9
// Tool Versions: Vivado v. 2019.2
10
// License: CERN-OHL-W
11
// Description: This pipeline stage comes after the decoder.
12
// It contains the integer register file. Register read requests come from the
13
// decoder stage and nowhere else. Register write commands come from the result buses.
14
// Tags are written to the register entries for values in flight in the pipeline.
15
//
16
// Putting the register file into this pipeline stage rather than in a separate module
17
// saves a lot of synchronization problems when results from a separate register file
18
// may come at a wrong clock cycle due to pipeline stall.
19
// This does not make this module excessively big.
20
//
21
//////////////////////////////////////////////////////////////////////////////////
22
`include "defines.vh"
23
 
24
 
25
module register_read (
26
    input clock,                            // system clock (100 MHz)
27
    input clock_enable,                     // clock enable. Used when single-stepping
28
    input reset,                            // system reset.
29
    input valid_in,                         // data from fetch module ready
30
    input stall_in,                         // a later stage in pipeline is stalled
31
    input [`CODE_ADDR_WIDTH-1:0] instruction_pointer_in, // address of current instruction
32
    input [95:0] instruction_in,            // current instruction, up to 3 words long
33
    input        tag_write_in,              // write tag
34
    input [`TAG_WIDTH-1:0] tag_val_in,      // instruction tag value
35
    input        vector_in,                 // this is a vector instruction
36
    input [1:0]  category_in,               // 00: multiformat, 01: single format, 10: jump
37
    input [1:0]  format_in,                 // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder)
38
    input [2:0]  rs_status_in,              // use of RS
39
    input [2:0]  rt_status_in,              // Use of RT
40
    input [1:0]  ru_status_in,              // Use of RU
41
    input [1:0]  rd_status_in,              // Use of RD as input
42
    input [1:0]  mask_status_in,            // Use of mask register
43
    input        mask_options_in,           // mask register may contain options
44
    input        mask_alternative_in,       // mask register and fallback register used for alternative purposes
45
    input [2:0]  fallback_use_in,           // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT
46
    input [1:0]  num_operands_in,           // number of source operands
47
    input [1:0]  result_type_in,            // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing
48
    input [1:0]  offset_field_in,           // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit
49
    input [1:0]  immediate_field_in,        // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit
50
    input [1:0]  scale_factor_in,           // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1
51
    input        index_limit_in,            // IM2 or IM3 contains a limit to the index
52
 
53
    // ports for register write
54
    input [`RB1:0] writeport1,              // write port 1
55
    input [5:0] writea1,                    // address input for writeport1 (extra bit is 1 for system registers)
56
    input write_en1,                        // write enable for writeport1
57
    input [`TAG_WIDTH-1:0] write_tag1,      // tag must match to enable writing
58
    input [`RB1:0] writeport2,
59
    input [4:0] writea2,
60
    input write_en2,
61
    input [`TAG_WIDTH-1:0] write_tag2,
62
    input [5:0] debug_reada,                // read port for debugger
63
 
64
    output reg        valid_out,            // An instruction is ready for output to next stage
65
    output reg [`CODE_ADDR_WIDTH-1:0] instruction_pointer_out, // address of current instruction
66
    output reg [95:0] instruction_out,      // first word of instruction
67
    output reg        stall_predict_out,    // predict next stage will stall
68
 
69
    output reg [`TAG_WIDTH-1:0] tag_val_out,// instruction tag value
70
    output reg        vector_out,           // this is a vector instruction
71
    output reg [1:0]  category_out,         // 00: multiformat, 01: single format, 10: jump
72
    output reg [1:0]  format_out,           // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder)
73
    output reg [1:0]  num_operands_out,     // number of source operands
74
    output reg [1:0]  result_type_out,      // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing
75
    output reg [1:0]  offset_field_out,     // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit
76
    output reg [1:0]  immediate_field_out,  // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit
77
    output reg [1:0]  scale_factor_out,     // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1
78
    output reg        index_limit_out,      // IM2 or IM3 contains a limit to the index
79
 
80
    output reg [`RB:0] rd_val_out,          // value of register operand RD, bit `RB indicates missing
81
    output reg [`RB:0] rs_val_out,          // value of register operand RS, bit `RB indicates missing
82
    output reg [`RB:0] rt_val_out,          // value of register operand RT, bit `RB indicates missing
83
    output reg [`RB:0] ru_val_out,          // value of register operand RU, bit `RB indicates missing
84
    output reg [`MASKSZ:0]  regmask_val_out,// value of mask register, bit 32 indicates missing
85
 
86
    output reg [1:0]   rd_status_out,       // uas of RD as input
87
    output reg [2:0]   rs_status_out,       // use of RS
88
    output reg [2:0]   rt_status_out,       // use of RT
89
    output reg [1:0]   ru_status_out,       // use of RU
90
    output reg [1:0]   mask_status_out,     // 1: mask register is used
91
    output reg         mask_alternative_out,// mask register and fallback register used for alternative purposes
92
    output reg [2:0]   fallback_use_out,    // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT
93
    output reg [32:0]  debugport_out        // read for debugging purpose
94
);
95
 
96
// components of instruction
97
logic [1:0]  il;                            // instruction length
98
logic [2:0]  ot;                            // operand type
99
logic [4:0]  mask;                          // mask register number
100
logic [4:0]  rd;                            // rd register number
101
logic [5:0]  rs;                            // rs register number
102
logic [5:0]  rt;                            // rt register number
103
logic [4:0]  ru;                            // ru register number
104
logic [5:0]  tag_a;                         // tag address
105
 
106
// register values. Extra bit is 1 if not found
107
logic [`RB:0] rd_val;                       // value of register RD
108
logic [`RB:0] rs_val;                       // value of register RS
109
logic [`RB:0] rt_val;                       // value of register RT
110
logic [`RB:0] ru_val;                       // value of register RU
111
logic [`MASKSZ:0]  mask_val;                // value of mask register
112
logic         mask_used;                    // a mask register is used
113
logic         mask_off;                     // mask is known to be 0. input operands are not used. fallback may be used
114
logic         stall_predict;                // predict that address generator will stall in next clock cycle
115
logic [`COMMON_ADDR_WIDTH:0] instr_end;     // address at end of instruction (word based)
116
 
117
logic [`TAG_WIDTH:0] rd_tag;                // tag to look for if rd not available
118
logic [`TAG_WIDTH:0] rs_tag;                // tag to look for if rs not available
119
logic [`TAG_WIDTH:0] rt_tag;                // tag to look for if rt not available
120
logic [`TAG_WIDTH:0] ru_tag;                // tag to look for if ru not available
121
logic [`TAG_WIDTH:0] mask_tag;              // tag to look for if mask not available
122
 
123
// temporary debug info
124
logic [31:0] debug_bits;
125
logic [31:0] debug_bits_tag;
126
 
127
// temporary storage of register values during stall. Extra bit is 1 if not found
128
reg [`RB:0] rd_val_temp;                    // temporary value of register RD
129
reg [`RB:0] rs_val_temp;                    // temporary value of register RS
130
reg [`RB:0] rt_val_temp;                    // temporary value of register RT
131
reg [`RB:0] ru_val_temp;                    // temporary value of register RU
132
reg [`MASKSZ:0] mask_val_temp;              // temporary value of mask mask register
133
reg         last_stall;                     // was stalled in last clock cycle. May obtain values from the temporary registers
134
 
135
always_comb begin
136
// extract instruction fields, etc
137
    il   = instruction_in[`IL];
138
    ot   = instruction_in[`OT];
139
    mask = instruction_in[`MASK];
140
    rd   = instruction_in[`RD];
141
    rs   = {(rs_status_in == `REG_SYSTEM), instruction_in[`RS]};
142
    rt   = instruction_in[`RT];
143
    ru   = instruction_in[`RU];
144
    if (mask_status_in != `REG_UNUSED && instruction_in[`MASK] == 7) mask = `NUMCONTR;
145
    if (rs_status_in == `REG_POINTER && offset_field_in >= `OFFSET_2) begin
146
        if (instruction_in[`RS] == 28) rs = `THREADP;
147
        if (instruction_in[`RS] == 29) rs = `DATAP;
148
    end
149
    /*
150
    if (rt_status_in == `REG_POINTER && offset_field_in >= `OFFSET_2) begin
151
        if (instruction_in[`RT] == 28) rt = `THREADP;
152
        if (instruction_in[`RT] == 29) rt = `DATAP;
153
    end    */
154
    tag_a = {result_type_in == `RESULT_SYS, rd}; // tag address
155
    instr_end = instruction_pointer_in + (il[1] ? il : 2'b01) + {1'b1,{(`CODE_ADDR_START-2){1'b0}}}; // address at end of instruction
156
end
157
 
158
/************************************************************
159
         general purpose and system register file
160
*************************************************************
161
Values of read addresses:
162
0-30: register r0 - r30
163
31:   data stack pointer
164
32:   numeric control register
165
33:   thread pointer
166
34:   data section pointer
167
35:   currently unused
168
************************************************************/
169
 
170
parameter num_reg = 32 + `NUM_SYS_REGISTERS;     // 32 general purpose registers and 3 system registers
171
reg [`RB:0] registers [num_reg];
172
 
173
// writing to registers through write ports
174
// generation loop for all general purpose and system registers
175
genvar i;
176
for (i=0; i < num_reg; i++) begin
177
    always_ff @(posedge clock) if (clock_enable) begin
178
        if (reset)
179
            registers[i] <= 0; // reset general purpose registers, but not system registers
180
        else if (tag_write_in && valid_in && i == tag_a)
181
            registers[i] <= {1'b1, {(`RB-`TAG_WIDTH){1'b0}}, tag_val_in};
182
        else if (write_en1 && i == writea1 && write_tag1 == registers[i][`TAG_WIDTH-1:0])
183
            registers[i] <= {1'b0,writeport1};
184
        else if (write_en2 && i == writea2 && write_tag2 == registers[i][`TAG_WIDTH-1:0])
185
            registers[i] <= {1'b0,writeport2};
186
    end
187
end
188
 
189
// get general purpose and system register values
190
always_comb begin
191
    // tags to look for if registers are not available
192
    if (last_stall) begin
193
        // the tags to look for must be sampled in the first clock cycle of a stall
194
        rd_tag   = {rd_val_temp[`RB],rd_val_temp[`TAG_WIDTH-1:0]};
195
        rs_tag   = {rs_val_temp[`RB],rs_val_temp[`TAG_WIDTH-1:0]};
196
        rt_tag   = {rt_val_temp[`RB],rt_val_temp[`TAG_WIDTH-1:0]};
197
        ru_tag   = {ru_val_temp[`RB],ru_val_temp[`TAG_WIDTH-1:0]};
198
        mask_tag = {mask_val_temp[`MASKSZ],mask_val_temp[`TAG_WIDTH-1:0]};
199
    end else begin
200
        // the tags to look for are found in the register file
201
        rd_tag   = {registers[rd][`RB],registers[rd][`TAG_WIDTH-1:0]};
202
        rs_tag   = {registers[rs][`RB],registers[rs][`TAG_WIDTH-1:0]};
203
        rt_tag   = {registers[rt][`RB],registers[rt][`TAG_WIDTH-1:0]};
204
        ru_tag   = {registers[ru][`RB],registers[ru][`TAG_WIDTH-1:0]};
205
        mask_tag = {registers[mask][`RB],registers[mask][`TAG_WIDTH-1:0]};
206
    end
207
 
208
    if (rd_status_in == `REG_UNUSED) begin
209
        rd_val = 0;
210
    end else if (write_en1 && rd == writea1 && rd_tag[`TAG_WIDTH] && write_tag1 == rd_tag[`TAG_WIDTH-1:0]) begin
211
        rd_val = {1'b0,writeport1};         // forwarding from write port 1
212
    end else if (write_en2 && rd == writea2 && rd_tag[`TAG_WIDTH] && write_tag2 == rd_tag[`TAG_WIDTH-1:0]) begin
213
        rd_val = {1'b0,writeport2};         // forwarding from write port 2
214
    end else if (last_stall) begin
215
        rd_val = rd_val_temp;
216
    end else begin
217
        rd_val = registers[rd];             // read value or tag from register file
218
    end
219
 
220
    if (rs_status_in == `REG_UNUSED) begin
221
        rs_val = 0;
222
    end else if (rs_status_in == `REG_POINTER && offset_field_in >= `OFFSET_2 && instruction_in[`RS] == 30) begin
223
        rs_val = {instr_end,2'b0};             // instruction pointer as base pointer
224
    end else if (write_en1 && rs == writea1 && rs_tag[`TAG_WIDTH] && write_tag1 == rs_tag[`TAG_WIDTH-1:0]) begin
225
        rs_val = {1'b0,writeport1};         // forwarding from write port 1
226
    end else if (write_en2 && rs == writea2 && rs_tag[`TAG_WIDTH] && write_tag2 == rs_tag[`TAG_WIDTH-1:0]) begin
227
        rs_val = {1'b0,writeport2};         // forwarding from write port 2
228
    end else if (last_stall) begin
229
        rs_val = rs_val_temp;
230
    end else begin
231
        rs_val = registers[rs];             // read value or tag from register file
232
    end
233
 
234
    if (rt_status_in == `REG_UNUSED) begin
235
        rt_val = 0;
236
    //end else if (rt_status_in == `REG_POINTER && offset_field_in >= `OFFSET_2 && instruction_in[`RT] == 30) begin
237
    //    rt_val = {instr_end,2'b0} ; // instruction pointer as base pointer
238
    end else if (write_en1 && rt == writea1 && rt_tag[`TAG_WIDTH] && write_tag1 == rt_tag[`TAG_WIDTH-1:0]) begin
239
        rt_val = {1'b0,writeport1};         // forwarding from write port 1
240
    end else if (write_en2 && rt == writea2 && rt_tag[`TAG_WIDTH] && write_tag2 == rt_tag[`TAG_WIDTH-1:0]) begin
241
        rt_val = {1'b0,writeport2};         // forwarding from write port 2
242
    end else if (last_stall) begin
243
        rt_val = rt_val_temp;
244
    end else begin
245
        rt_val = registers[rt];             // read value or tag from register file
246
    end
247
 
248
    if (ru_status_in == `REG_UNUSED) begin
249
        ru_val = 0;
250
    end else if (write_en1 && ru == writea1 && ru_tag[`TAG_WIDTH] && write_tag1 == ru_tag[`TAG_WIDTH-1:0]) begin
251
        ru_val = {1'b0,writeport1};         // forwarding from write port 1
252
    end else if (write_en2 && ru == writea2 && ru_tag[`TAG_WIDTH] && write_tag2 == ru_tag[`TAG_WIDTH-1:0]) begin
253
        ru_val = {1'b0,writeport2};         // forwarding from write port 2
254
    end else if (last_stall) begin
255
        ru_val = ru_val_temp;
256
    end else begin
257
        ru_val = registers[ru];             // read value or tag from register file
258
    end
259
 
260
    if (mask_status_in == `REG_UNUSED) begin
261
        mask_val = 1;
262
    end else if (write_en1 && mask == writea1 && mask_tag[`TAG_WIDTH] && write_tag1 == mask_tag[`TAG_WIDTH-1:0]) begin
263
        mask_val = {1'b0,writeport1[`MASKSZ-1:0]};    // forwarding from write port 1
264
    end else if (write_en2 && mask == writea2 && mask_tag[`TAG_WIDTH] && write_tag2 == mask_tag[`TAG_WIDTH-1:0]) begin
265
        mask_val = {1'b0,writeport2[`MASKSZ-1:0]};    // forwarding from write port 2
266
    end else if (last_stall) begin
267
        mask_val = mask_val_temp;
268
    end else begin
269
        mask_val = {registers[mask][`RB],registers[mask][`MASKSZ-1:0]}; // read value or tag from register file
270
    end
271
end
272
 
273
// save values during stall
274
always_ff @(posedge clock) if (clock_enable && valid_in) begin
275
    last_stall <= stall_in;
276
    if (stall_in) begin
277
        rd_val_temp <= rd_val;
278
        rs_val_temp <= rs_val;
279
        rt_val_temp <= rt_val;
280
        ru_val_temp <= ru_val;
281
        mask_val_temp <= mask_val;
282
    end else begin
283
        rd_val_temp <= {1'b1,`RB'b0};
284
        rs_val_temp <= {1'b1,`RB'b0};
285
        rt_val_temp <= {1'b1,`RB'b0};
286
        ru_val_temp <= {1'b1,`RB'b0};
287
        mask_val_temp <= {1'b1,`MASKSZ'b0};
288
    end
289
end
290
 
291
 
292
always_comb begin
293
    // (The mask must be ignored for the NOP instruction. If there are any other instructions with
294
    // zero operands that can have a valid mask then the above line must be modified.)
295
    mask_used = (format_in == `FORMAT_A || format_in == `FORMAT_E) && mask != 7 && num_operands_in != 0;
296
    // Check if result is masked off so that we don't have to wait for operands
297
    mask_off = mask_used && mask_val[`MASKSZ] == 0 && mask_val[0] == 0 && !mask_alternative_in && !vector_in;
298
 
299
    stall_predict = 0;
300
    // rs used as pointer or index or vector length and not available in next clock cycle:
301
    if (rs_status_in >= `REG_POINTER && rs_val[`RB] && !mask_off) stall_predict = 1;
302
    // rt used as pointer and not available in next clock cycle:
303
    if (rt_status_in >= `REG_POINTER && rt_val[`RB] && !mask_off) stall_predict = 1;
304
    // rd is written to memory and not available in next clock cycle:
305
    if (rd_status_in != 0 && result_type_in == `RESULT_MEM && rd_val[`RB] && !mask_off) stall_predict = 1;
306
    // mask value is needed for memory write
307
    if (mask_used && result_type_in == `RESULT_MEM && mask_val[`MASKSZ]) stall_predict = 1;
308
 
309
    // signals for debugging
310
    debug_bits = 0;
311
    debug_bits[0]  = rs_status_in >= `REG_POINTER;
312
 
313
    debug_bits[8]  = rt_status_in >= `REG_POINTER;
314
 
315
    debug_bits[16] = rd_status_in;
316
 
317
    debug_bits[24] = stall_predict;
318
    debug_bits[25] = last_stall;
319
    debug_bits[26] = stall_in;
320
    debug_bits[27] = valid_in;
321
 
322
    debug_bits_tag = 0;
323
    //debug_bits_tag[`TAG_WIDTH-1:0] = tag_mirror[reg1_in];
324
 
325
end
326
 
327
// get values of missing operands from result buses.
328
// if stalling: keep looking for results and keep the values until not stalled
329
always_ff @(posedge clock) if (clock_enable) begin
330
 
331
    // Predict stall in next stage if RS, RT, or RD is needed in the address generator stage
332
    // and not yet available and not predicted to become available in the next clock cycle.
333
    // Note, that while the stall prediction is looking forward one stage in the pipeline,
334
    // it should not apply if the instruction is not moving to the next stage yet, hence
335
    // stall_predict_out is not applied if stall_in.
336
    stall_predict_out <= stall_predict && !stall_in && !reset && valid_in;
337
 
338
    if (reset) valid_out <= 0;
339
    else if (!stall_in) valid_out <= valid_in;
340
end
341
 
342
// generate outputs
343
always_ff @(posedge clock) if (clock_enable && !stall_in) begin
344
    // first two words of instruction
345
    instruction_out <= instruction_in;
346
 
347
    // register values out
348
    rd_val_out <= rd_val;                   // value of register operand RD, bit `RB indicates missing
349
    rs_val_out <= rs_val;                   // value of register operand RS, bit `RB indicates missing
350
    rt_val_out <= rt_val;                   // value of register operand RT, bit `RB indicates missing
351
    ru_val_out <= ru_val;                   // value of register operand RU, bit `RB indicates missing
352
    regmask_val_out <= mask_val;            // value of mask register, bit 32 indicates missing
353
 
354
    // other outputs are unchanged from input
355
    instruction_pointer_out <= instruction_pointer_in;
356
    tag_val_out <= tag_val_in;              // tag for current instruction
357
    vector_out <= vector_in;                // vector instruction
358
    category_out <= category_in;            // instruction category
359
    format_out <= format_in;                // instruction format
360
    rs_status_out <= rs_status_in;          // use of rs register
361
    rt_status_out <= rt_status_in;          // use of rt register
362
    ru_status_out <= ru_status_in;          // use of ru register
363
    rd_status_out <= rd_status_in;          // use of rd register
364
    mask_status_out <=  mask_used | mask_options_in; // use of mask register
365
    mask_alternative_out <= mask_alternative_in; // mask register and fallback register used for alternative purposes
366
    fallback_use_out <= fallback_use_in;    // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT
367
    num_operands_out <= num_operands_in;    // number of input operands
368
    result_type_out <= result_type_in;      // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing
369
    offset_field_out <= offset_field_in;    // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit
370
    immediate_field_out <= immediate_field_in; // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit
371
    scale_factor_out <= scale_factor_in;    // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1
372
    index_limit_out <= index_limit_in;      // The field indicated by offset_field contains a limit to the index
373
end
374
 
375
always_ff @(posedge clock) begin
376
    debugport_out <= registers[debug_reada];// read register by debugger
377
end
378
 
379
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.