1 /******************************************************************************
  2 * Copyright 2013, Hectic Tech (Jeff Heckey). All rights reserved
  3 ******************************************************************************/
  4 
  5 module cf #(
  6     parameter PC = 8,
  7     parameter OP = 3,
  8     parameter TAG = 4,
  9     parameter DATA = 32
 10 ) (
 11     input  wire                     clk,
 12     input  wire                     rstn,
 13 
 14     input  wire [PC-1:0]            pc,
 15     input  wire [OP+4*TAG-1:0]      disp_bus0,
 16     input  wire [OP+4*TAG-1:0]      disp_bus1,
 17     input  wire                     cdb_a_except,
 18     input  wire [TAG-1:0]           cdb_a_id,
 19     input  wire [DATA-1:0]          cdb_a_data,
 20     input  wire                     cdb_m_except,
 21     input  wire [TAG-1:0]           cdb_m_id,
 22     input  wire [DATA-1:0]          cdb_m_data,
 23     input  wire                     cdb_l_except,
 24     input  wire [TAG-1:0]           cdb_l_id,
 25     input  wire [DATA-1:0]          cdb_l_data,
 26     input  wire                     cdb_s_except,
 27     input  wire [TAG-1:0]           cdb_s_id,
 28 
 29     output reg                      exception,
 30     output reg  [PC-1:0]            comp_pc,
 31     output reg                      clean,
 32     output reg                      cf_val,
 33     output reg  [TAG-1:0]           cf_addr,
 34     output reg  [DATA-1:0]          cf_data
 35 );
 36 
 37 localparam RUN      = 3'b000,
 38            EXCEPT   = 3'b001,
 39            CLEAN0   = 3'b100,
 40            CLEAN1   = 3'b101,
 41            CLEAN2   = 3'b110,
 42            CLEAN3   = 3'b111,
 43            CLEAN    = 3'b011;
 44 localparam DEPTH = 32;
 45 localparam R0 = 4'd4,
 46            R1 = 4'd5,
 47            R2 = 4'd6,
 48            R3 = 4'd7,
 49            A0 = 4'd8,
 50            A1 = 4'd9,
 51            M0 = 4'd10,
 52            M1 = 4'd11,
 53            L0 = 4'd12,
 54            L1 = 4'd13,
 55            S0 = 4'd14,
 56            S1 = 4'd15;
 57 
 58 reg                         exceptionN, exception_nextN;
 59 reg  [4:0]                  insert, insert_next, insertN, insert_1N;
 60 reg  [4:0]                  complete, complete_next, completeN;
 61 reg  [1:0]                  comp_update;
 62 
 63 // Format: Valid, Exception, Complete, PC, RSV Tag, DST Tag, DATA
 64 reg  [3+PC+2*TAG+DATA-1:0]  cfile[DEPTH-1:0];
 65 reg  [3+PC+2*TAG+DATA-1:0]  cfileN[DEPTH-1:0];
 66 reg  [3+PC+2*TAG+DATA-1:0]  cfile_nextN[DEPTH-1:0];
 67 
 68 reg  [DATA-1:0]             srfile[3:0];
 69 reg  [DATA-1:0]             srfile_next[3:0];
 70 reg  [DATA-1:0]             srfileN[3:0];
 71 reg  [2:0]                  state, state_next, stateN;
 72 
 73 
 74 reg  [PC-1:0]           pcN;
 75 reg  [OP+4*TAG-1:0]     disp_bus0N;
 76 reg  [OP+4*TAG-1:0]     disp_bus1N;
 77 reg                     cdb_a_exceptN;
 78 reg  [TAG-1:0]          cdb_a_idN;
 79 reg  [DATA-1:0]         cdb_a_dataN;
 80 reg                     cdb_m_exceptN;
 81 reg  [TAG-1:0]          cdb_m_idN;
 82 reg  [DATA-1:0]         cdb_m_dataN;
 83 reg                     cdb_l_exceptN;
 84 reg  [TAG-1:0]          cdb_l_idN;
 85 reg  [DATA-1:0]         cdb_l_dataN;
 86 reg                     cdb_s_exceptN;
 87 reg  [TAG-1:0]          cdb_s_idN;
 88 
 89 reg  [TAG-1:0]          disp0_rsvN;
 90 reg  [TAG-1:0]          disp0_dstN;
 91 reg  [TAG-1:0]          disp1_rsvN;
 92 reg  [TAG-1:0]          disp1_dstN;
 93 reg                     ins0_val;
 94 reg                     ins0_exp;
 95 reg                     ins0_comp;
 96 reg  [PC-1:0]           ins0_pc;
 97 reg  [TAG-1:0]          ins0_rsv;
 98 reg  [TAG-1:0]          ins0_dst;
 99 reg  [DATA-1:0]         ins0_data;
100 reg                     ins1_val;
101 reg                     ins1_exp;
102 reg                     ins1_comp;
103 reg  [PC-1:0]           ins1_pc;
104 reg  [TAG-1:0]          ins1_rsv;
105 reg  [TAG-1:0]          ins1_dst;
106 reg  [DATA-1:0]         ins1_data;
107 reg                     comp0_val;
108 reg                     comp0_exp;
109 reg                     comp0_comp;
110 reg  [PC-1:0]           comp0_pc;
111 reg  [TAG-1:0]          comp0_rsv;
112 reg  [TAG-1:0]          comp0_dst;
113 reg  [DATA-1:0]         comp0_data;
114 reg                     comp1_val;
115 reg                     comp1_exp;
116 reg                     comp1_comp;
117 reg  [PC-1:0]           comp1_pc;
118 reg  [TAG-1:0]          comp1_rsv;
119 reg  [TAG-1:0]          comp1_dst;
120 reg  [DATA-1:0]         comp1_data;
121 reg                     comp2_val;
122 reg                     comp2_exp;
123 reg                     comp2_comp;
124 reg  [PC-1:0]           comp2_pc;
125 reg  [TAG-1:0]          comp2_rsv;
126 reg  [TAG-1:0]          comp2_dst;
127 reg  [DATA-1:0]         comp2_data;
128 reg                     update_valN;
129 reg                     update_expN;
130 reg                     update_compN;
131 reg  [PC-1:0]           update_pcN;
132 reg  [TAG-1:0]          update_rsvN;
133 reg  [TAG-1:0]          update_dstN;
134 reg  [DATA-1:0]         update_dataN;
135 
136 integer i, j, k;
137 
138 always @* begin : CF_POS_PHASE
139     { ins0_val,
140       ins0_exp,
141       ins0_comp,
142       ins0_pc,
143       ins0_rsv,
144       ins0_dst,
145       ins0_data }   = cfile[insert];
146     { ins1_val,
147       ins1_exp,
148       ins1_comp,
149       ins1_pc,
150       ins1_rsv,
151       ins1_dst,
152       ins1_data }   = cfile[insert+8'd1];
153 
154     { comp0_val,
155       comp0_exp,
156       comp0_comp,
157       comp0_pc,
158       comp0_rsv,
159       comp0_dst,
160       comp0_data }  = cfile[complete];
161     { comp1_val,
162       comp1_exp,
163       comp1_comp,
164       comp1_pc,
165       comp1_rsv,
166       comp1_dst,
167       comp1_data }  = cfile[complete+8'd1];
168     { comp2_val,
169       comp2_exp,
170       comp2_comp,
171       comp2_pc,
172       comp2_rsv,
173       comp2_dst,
174       comp2_data }  = cfile[complete+8'd2];
175 
176     // Dispatch will only occur when no exception is found
177     insert_next = ( |ins0_rsv && |ins1_rsv ) ? insert + 5'd2
178                   : ( |ins0_rsv ) ? insert + 5'd1
179                   : insert;
180 
181     // Normally some exit from the exception state will be possible, but not
182     // handled in this project
183     // Update complete pointer by up to 2 if subsequent commands are complete, 
184     // but not if they are LOAD or STOR exceptions (we want to pretend that
185     // never happened)
186     if ( comp0_comp && !comp0_exp
187          && ( comp1_comp && !comp1_exp )
188          && ( comp2_comp && !( comp2_rsv[3:2] == 2'b11 && comp2_exp ) ) ) begin
189         complete_next   = complete + 5'd2;
190         comp_update     = 2'b11;
191     end
192     else if ( comp0_comp && !comp0_exp
193               && ( comp1_comp && !( comp1_rsv[3:2] == 2'b11 && comp1_exp ) ) ) begin
194         complete_next   = complete + 5'd1;
195         comp_update     = 2'b01;
196     end
197     else begin
198         complete_next   = complete;
199         comp_update     = 2'b00;
200     end
201 
202     for ( j = 0; j < 4; j = j+1 ) begin
203         if ( comp_update[1] && comp2_comp && comp2_dst == (R0 + j) ) begin
204             srfile_next[j] = comp1_data;
205         end
206         else if ( comp_update[0] && comp1_comp && comp1_dst == (R0 + j) ) begin
207             srfile_next[j] = comp0_data;
208         end
209         else if ( comp0_comp && comp0_dst == (R0 + j) ) begin
210             srfile_next[j] = comp0_data;
211         end
212         else begin
213             srfile_next[j] = srfile[j];
214         end
215     end
216 
217     // Update state - RUN until exception; EXCEPT until all have completed;
218     // CLEAN0-3 to restore registers, CLEAN after that.
219     case ( stateN )
220     RUN:    state_next = ( exception ) ? EXCEPT : RUN;
221     EXCEPT: state_next = ( comp0_exp || ( comp1_rsv[3:2] == 2'b11 && comp1_exp ) ) ? CLEAN0 : EXCEPT;
222     CLEAN0: state_next = CLEAN1;
223     CLEAN1: state_next = CLEAN2;
224     CLEAN2: state_next = CLEAN3;
225     CLEAN3: state_next = CLEAN;
226     CLEAN:  state_next = CLEAN;
227     endcase
228 end
229 
230 always @( negedge clk or negedge rstn ) begin : CF_NEG_LATCHES
231     if ( !rstn ) begin
232         insertN         <= 5'd0;
233         completeN       <= 5'd0;
234         exceptionN      <= 1'b0;
235         stateN          <= RUN;
236 
237         pcN             <= {PC{1'b0}};
238         disp_bus0N      <= {OP+4*TAG{1'b0}};
239         disp_bus1N      <= {OP+4*TAG{1'b0}};
240         cdb_a_exceptN   <= 1'b0;
241         cdb_a_idN       <= {TAG{1'b0}};
242         cdb_a_dataN     <= {DATA{1'b0}};
243         cdb_m_exceptN   <= 1'b0;
244         cdb_m_idN       <= {TAG{1'b0}};
245         cdb_m_dataN     <= {DATA{1'b0}};
246         cdb_l_exceptN   <= 1'b0;
247         cdb_l_idN       <= {TAG{1'b0}};
248         cdb_l_dataN     <= {DATA{1'b0}};
249         cdb_s_exceptN   <= 1'b0;
250         cdb_s_idN       <= {TAG{1'b0}};
251 
252         for ( i=0; i<DEPTH; i=i+1 ) begin
253             cfileN[i]   <= {PC+2*TAG+DATA+2{1'b0}};
254         end
255 
256         for ( i=0; i<4; i=i+1 ) begin
257             srfileN[i]  <= {DATA{1'b0}};
258         end
259     end
260     else begin
261         if ( !clk ) begin
262             insertN         <= insert_next;
263             completeN       <= complete_next;
264             exceptionN      <= exception;
265             stateN          <= state_next;
266 
267             pcN             <= pc;
268             disp_bus0N      <= disp_bus0;
269             disp_bus1N      <= disp_bus1;
270             cdb_a_exceptN   <= cdb_a_except;
271             cdb_a_idN       <= cdb_a_id;
272             cdb_a_dataN     <= cdb_a_data;
273             cdb_m_exceptN   <= cdb_m_except;
274             cdb_m_idN       <= cdb_m_id;
275             cdb_m_dataN     <= cdb_m_data;
276             cdb_l_exceptN   <= cdb_l_except;
277             cdb_l_idN       <= cdb_l_id;
278             cdb_l_dataN     <= cdb_l_data;
279             cdb_s_exceptN   <= cdb_s_except;
280             cdb_s_idN       <= cdb_s_id;
281 
282             for ( i=0; i<DEPTH; i=i+1 ) begin
283                 cfileN[i]   <= cfile[i];
284             end
285 
286             for ( i=0; i<4; i=i+1 ) begin
287                 srfileN[i]  <= srfile_next[i];
288             end
289         end
290     end
291 end
292 
293 integer iN, jN;
294 
295 always @* begin : CF_NEG_PHASE
296     exception_nextN  = exceptionN || cdb_a_except || cdb_m_except || cdb_l_except || cdb_s_except;
297 
298     disp0_rsvN = disp_bus0N[OP+4*TAG-1:OP+3*TAG];
299     disp0_dstN = disp_bus0N[3*TAG-1:2*TAG];
300     disp1_rsvN = disp_bus1N[OP+4*TAG-1:OP+3*TAG];
301     disp1_dstN = disp_bus1N[3*TAG-1:2*TAG];
302 
303     insert_1N  = insertN + 5'd1;
304 
305     // Update completion file
306     for ( jN = 0; jN < DEPTH; jN = jN+1 ) begin
307         { update_valN,
308           update_expN,
309           update_compN,
310           update_pcN,
311           update_rsvN,
312           update_dstN,
313           update_dataN }    = cfileN[jN];
314 
315         // Update logic for each element
316         if ( jN == insertN && |disp0_rsvN ) begin
317             cfile_nextN[jN] = { 1'b1,       // valid
318                                 1'b0,       // no exception
319                                 1'b0,       // not complete
320                                 pcN,
321                                 disp0_rsvN,
322                                 disp0_dstN,
323                                 32'd0 };    // data
324         end
325         else if ( jN == insert_1N && |disp1_rsvN ) begin
326             cfile_nextN[jN] = { 1'b1,       // valid
327                                 1'b0,       // no exception
328                                 1'b0,       // not complete
329                                 pcN + {{PC-1{1'b0}},1'b1},
330                                 disp1_rsvN,
331                                 disp1_dstN,
332                                 32'd0 };    // data
333         end
334         else if ( update_valN && !update_expN && !update_compN ) begin
335             case ( update_rsvN )
336             A0:
337             begin
338                 if ( cdb_a_idN == A0 ) begin
339                     cfile_nextN[jN] = { update_valN,
340                                         cdb_a_exceptN,
341                                         1'b1,
342                                         update_pcN,
343                                         update_rsvN,
344                                         update_dstN,
345                                         cdb_a_data };
346                 end
347                 else begin
348                     cfile_nextN[jN] = cfileN[jN];
349                 end
350             end
351 
352             A1:
353             begin
354                 if ( cdb_a_idN == A1 ) begin
355                     cfile_nextN[jN] = { update_valN,
356                                         cdb_a_exceptN,
357                                         1'b1,
358                                         update_pcN,
359                                         update_rsvN,
360                                         update_dstN,
361                                         cdb_a_data };
362                 end
363                 else begin
364                     cfile_nextN[jN] = cfileN[jN];
365                 end
366             end
367 
368             M0:
369             begin
370                 if ( cdb_m_idN == M0 ) begin
371                     cfile_nextN[jN] = { update_valN,
372                                         cdb_m_exceptN,
373                                         1'b1,
374                                         update_pcN,
375                                         update_rsvN,
376                                         update_dstN,
377                                         cdb_m_data };
378                 end
379                 else begin
380                     cfile_nextN[jN] = cfileN[jN];
381                 end
382             end
383 
384             M1:
385             begin
386                 if ( cdb_m_idN == M1 ) begin
387                     cfile_nextN[jN] = { update_valN,
388                                         cdb_m_exceptN,
389                                         1'b1,
390                                         update_pcN,
391                                         update_rsvN,
392                                         update_dstN,
393                                         cdb_m_data };
394                 end
395                 else begin
396                     cfile_nextN[jN] = cfileN[jN];
397                 end
398             end
399 
400             L0:
401             begin
402                 if ( cdb_l_idN == L0 ) begin
403                     cfile_nextN[jN] = { update_valN,
404                                         cdb_l_exceptN,
405                                         1'b1,
406                                         update_pcN,
407                                         update_rsvN,
408                                         update_dstN,
409                                         cdb_l_data };
410                 end
411                 else begin
412                     cfile_nextN[jN] = cfileN[jN];
413                 end
414             end
415 
416             L1:
417             begin
418                 if ( cdb_l_idN == L1 ) begin
419                     cfile_nextN[jN] = { update_valN,
420                                         cdb_l_exceptN,
421                                         1'b1,
422                                         update_pcN,
423                                         update_rsvN,
424                                         update_dstN,
425                                         cdb_l_data };
426                 end
427                 else begin
428                     cfile_nextN[jN] = cfileN[jN];
429                 end
430             end
431 
432             S0:
433             begin
434                 if ( cdb_s_idN == S0 ) begin
435                     cfile_nextN[jN] = { update_valN,
436                                         cdb_s_exceptN,
437                                         1'b1,
438                                         update_pcN,
439                                         update_rsvN,
440                                         update_dstN,
441                                         {DATA{1'b0}} };
442                 end
443                 else begin
444                     cfile_nextN[jN] = cfileN[jN];
445                 end
446             end
447 
448             S1:
449             begin
450                 if ( cdb_s_idN == S1 ) begin
451                     cfile_nextN[jN] = { update_valN,
452                                         cdb_s_exceptN,
453                                         1'b1,
454                                         update_pcN,
455                                         update_rsvN,
456                                         update_dstN,
457                                         {DATA{1'b0}} };
458                 end
459                 else begin
460                     cfile_nextN[jN] = cfileN[jN];
461                 end
462             end
463 
464             default:
465                 $display ( "%t: INVALID cfile entry %h (rsv = %h)\n", $time,
466                         cfileN[jN], update_rsvN );
467             endcase
468         end
469         else begin
470             cfile_nextN[jN] = cfileN[jN];
471         end
472     end
473 end
474 
475 
476 always @( posedge clk or negedge rstn ) begin : CF_POS_LATCHES
477     if ( !rstn ) begin
478         state       <= RUN;
479 
480         insert      <= 5'd0;
481         complete    <= 5'd0;
482 
483         exception   <= 1'b0;
484         comp_pc     <= {PC{1'b0}};
485         clean       <= 1'b0;
486         cf_val      <= 1'b0;
487         cf_addr     <= {TAG{1'b0}};
488         cf_data     <= {DATA{1'b0}};
489 
490         for ( iN=0; iN<DEPTH; iN=iN+1 ) begin
491             cfile[iN]   <= {PC+2*TAG+DATA+3{1'b0}};
492         end
493 
494         for ( iN=0; iN<4; iN=iN+1 ) begin
495             srfile[iN]  <= {DATA{1'b0}};
496         end
497     end
498     else begin
499         if ( clk ) begin
500             state       <= stateN;
501             insert      <= insertN;
502             complete    <= completeN;
503             exception   <= exception_nextN;
504             comp_pc     <= cfileN[completeN][PC+2*TAG+DATA-1:2*TAG+DATA];
505 
506             case ( stateN )
507             RUN,
508             EXCEPT:
509             begin
510                 clean   <= 1'b0;
511                 cf_val  <= 1'b0;
512                 cf_addr <= {TAG{1'b0}};
513                 cf_data <= {DATA{1'b0}};
514             end
515 
516             CLEAN0:
517             begin
518                 clean   <= 1'b0;
519                 cf_val  <= 1'b1;
520                 cf_addr <= R0;
521                 cf_data <= srfileN[0];
522             end
523 
524             CLEAN1:
525             begin
526                 clean   <= 1'b0;
527                 cf_val  <= 1'b1;
528                 cf_addr <= R1;
529                 cf_data <= srfileN[1];
530             end
531 
532             CLEAN2:
533             begin
534                 clean   <= 1'b0;
535                 cf_val  <= 1'b1;
536                 cf_addr <= R2;
537                 cf_data <= srfileN[2];
538             end
539 
540             CLEAN3:
541             begin
542                 clean   <= 1'b0;
543                 cf_val  <= 1'b1;
544                 cf_addr <= R3;
545                 cf_data <= srfileN[3];
546             end
547 
548             CLEAN:
549             begin
550                 clean   <= 1'b1;
551                 cf_val  <= 1'b0;
552                 cf_addr <= {TAG{1'b0}};
553                 cf_data <= {DATA{1'b0}};
554             end
555 
556             endcase
557 
558             //$display( "Time: %t", $time );
559             for ( iN=0; iN<DEPTH; iN=iN+1 ) begin
560                 cfile[iN]   <= cfile_nextN[iN];
561                 //$display( "%d - V:%b, E:%b, C:%b, PC:%h, Rsv:%h, Dst:%h", iN,
562                 //            cfile_nextN[iN][50],
563                 //            cfile_nextN[iN][49],
564                 //            cfile_nextN[iN][48],
565                 //            cfile_nextN[iN][47:40],
566                 //            cfile_nextN[iN][39:36],
567                 //            cfile_nextN[iN][35:32] );
568             end
569             //$display( "\n" );
570 
571             for ( iN=0; iN<4; iN=iN+1 ) begin
572                 srfile[iN]  <= srfileN[iN];
573             end
574         end
575     end
576 end
577 
578 endmodule
579