1 /******************************************************************************
  2 * Copyright 2013, Hectic Tech (Jeff Heckey). All rights reserved
  3 ******************************************************************************/
  4 
  5 module store_rs #(
  6     parameter PC = 8,     // PC width
  7     parameter TAG = 4,    // Tag size
  8     parameter OP  = 3,    // OPCODE size
  9     parameter ADDR = 32,  // Address width
 10     parameter DATA = 32   // Address width
 11 ) (
 12     input  wire                     clk,
 13     input  wire                     rstn,
 14 
 15     input  wire [TAG-1:0]           cdb_r0_id,
 16     input  wire [DATA-1:0]          cdb_r0_data,
 17     input  wire [TAG-1:0]           cdb_r1_id,
 18     input  wire [DATA-1:0]          cdb_r1_data,
 19     input  wire [TAG-1:0]           cdb_r2_id,
 20     input  wire [DATA-1:0]          cdb_r2_data,
 21     input  wire [TAG-1:0]           cdb_a_id,
 22     input  wire [DATA-1:0]          cdb_a_data,
 23     input  wire [TAG-1:0]           cdb_m_id,
 24     input  wire [DATA-1:0]          cdb_m_data,
 25     input  wire [TAG-1:0]           cdb_l_id,
 26     input  wire [DATA-1:0]          cdb_l_data,
 27     input  wire [OP+4*TAG+ADDR-1:0] disp_bus0,
 28     input  wire [OP+4*TAG+ADDR-1:0] disp_bus1,
 29     input  wire [PC-1:0]            pc,
 30 
 31     input  wire [OP-1:0]            alt_op0,
 32     input  wire [ADDR-1:0]          alt_addr0,
 33     input  wire [OP-1:0]            alt_op1,
 34     input  wire [ADDR-1:0]          alt_addr1,
 35 
 36     output reg  [1:0]               func_val,
 37     input  wire [1:0]               func_ack,
 38     output reg  [PC-1:0]            func0_pc,
 39     output reg  [OP-1:0]            func0_op,
 40     output reg  [TAG-1:0]           func0_stall,
 41     output reg  [ADDR-1:0]          func0_address,
 42     output reg  [DATA-1:0]          func0_data,
 43     output reg  [PC-1:0]            func1_pc,
 44     output reg  [OP-1:0]            func1_op,
 45     output reg  [TAG-1:0]           func1_stall,
 46     output reg  [ADDR-1:0]          func1_address,
 47     output reg  [DATA-1:0]          func1_data
 48 );
 49 
 50 localparam L0 = 4'd12,
 51            L1 = 4'd13,
 52            S0 = 4'd14,
 53            S1 = 4'd15;
 54 
 55 reg  [TAG-1:0]              cdb_r0_idN;
 56 reg  [DATA-1:0]             cdb_r0_dataN;
 57 reg  [TAG-1:0]              cdb_r1_idN;
 58 reg  [DATA-1:0]             cdb_r1_dataN;
 59 reg  [TAG-1:0]              cdb_r2_idN;
 60 reg  [DATA-1:0]             cdb_r2_dataN;
 61 reg  [TAG-1:0]              cdb_a_idN;
 62 reg  [DATA-1:0]             cdb_a_dataN;
 63 reg  [TAG-1:0]              cdb_m_idN;
 64 reg  [DATA-1:0]             cdb_m_dataN;
 65 reg  [TAG-1:0]              cdb_l_idN;
 66 reg  [DATA-1:0]             cdb_l_dataN;
 67 reg  [OP+4*TAG+ADDR-1:0]    disp_bus0N;
 68 reg  [OP+4*TAG+ADDR-1:0]    disp_bus1N;
 69 reg  [TAG-1:0]              disp_rsv0N;
 70 reg  [OP-1:0]               disp_op0N;
 71 reg  [TAG-1:0]              disp_dst0N;
 72 reg  [TAG-1:0]              disp_src0N;
 73 reg  [ADDR-1:0]             disp_addr0N;
 74 reg  [TAG-1:0]              disp_rsv1N;
 75 reg  [OP-1:0]               disp_op1N;
 76 reg  [TAG-1:0]              disp_dst1N;
 77 reg  [TAG-1:0]              disp_src1N;
 78 reg  [ADDR-1:0]             disp_addr1N;
 79 reg  [PC-1:0]               pcN;
 80 reg  [OP-1:0]               alt_op0N;
 81 reg  [ADDR-1:0]             alt_addr0N;
 82 reg  [OP-1:0]               alt_op1N;
 83 reg  [ADDR-1:0]             alt_addr1N;
 84 reg  [TAG-1:0]              dummy_tagN;
 85 reg  [1:0]                  func_val_nextN;
 86 reg                         func0_loadN, func1_loadN;
 87 reg  [PC-1:0]               func0_pcN, func0_pc_nextN, func0_pc_next;
 88 reg  [OP-1:0]               func0_opN, func0_op_nextN, func0_op_next;
 89 reg  [TAG-1:0]              func0_stallN, func0_stall_nextN, func0_stall_next;
 90 reg  [ADDR-1:0]             func0_addressN, func0_address_nextN, func0_address_next;
 91 reg  [TAG-1:0]              func0_tag, func0_tagN, func0_tag_tempN, func0_tag_nextN, func0_tag_next;
 92 reg  [DATA-1:0]             func0_dataN, func0_data_nextN, func0_data_next;
 93 reg  [PC-1:0]               func1_pcN, func1_pc_nextN, func1_pc_next;
 94 reg  [OP-1:0]               func1_opN, func1_op_nextN, func1_op_next;
 95 reg  [TAG-1:0]              func1_stallN, func1_stall_nextN, func1_stall_next;
 96 reg  [ADDR-1:0]             func1_addressN, func1_address_nextN, func1_address_next;
 97 reg  [TAG-1:0]              func1_tag, func1_tagN, func1_tag_tempN, func1_tag_nextN, func1_tag_next;
 98 reg  [DATA-1:0]             func1_dataN, func1_data_nextN, func1_data_next;
 99 
100 always @* begin : LOAD_RS_POS_LOGIC
101     if ( func_ack[0] && func_val[0] ) begin
102         func0_pc_next       = {PC{1'b0}};
103         func0_op_next       = {OP{1'b0}};
104         func0_stall_next    = {TAG{1'b0}};
105         func0_address_next  = {ADDR{1'b0}};
106         func0_tag_next      = {TAG{1'b0}};
107         func0_data_next     = {DATA{1'b0}};
108     end
109     else begin
110         func0_pc_next       = func0_pc;
111         func0_op_next       = func0_op;
112         func0_stall_next    = func0_stall;
113         func0_address_next  = func0_address;
114         func0_tag_next      = func0_tag;
115         func0_data_next     = func0_data;
116     end
117 
118     if ( func_ack[1] && func_val[1] ) begin
119         func1_pc_next       = {PC{1'b0}};
120         func1_op_next       = {OP{1'b0}};
121         func1_stall_next    = {TAG{1'b0}};
122         func1_address_next  = {ADDR{1'b0}};
123         func1_tag_next      = {TAG{1'b0}};
124         func1_data_next     = {DATA{1'b0}};
125     end
126     else begin
127         func1_pc_next       = func1_pc;
128         func1_op_next       = func1_op;
129         func1_stall_next    = func1_stall;
130         func1_address_next  = func1_address;
131         func1_tag_next      = func1_tag;
132         func1_data_next     = func1_data;
133     end
134 end
135 
136 always @* begin : LOAD_RS_NEG_LATCHES
137     if ( !rstn ) begin
138         cdb_r0_idN      <= {TAG{1'b0}};
139         cdb_r0_dataN    <= {DATA{1'b0}};
140         cdb_r1_idN      <= {TAG{1'b0}};
141         cdb_r1_dataN    <= {DATA{1'b0}};
142         cdb_r2_idN      <= {TAG{1'b0}};
143         cdb_r2_dataN    <= {DATA{1'b0}};
144         cdb_a_idN       <= {TAG{1'b0}};
145         cdb_a_dataN     <= {DATA{1'b0}};
146         cdb_m_idN       <= {TAG{1'b0}};
147         cdb_m_dataN     <= {DATA{1'b0}};
148         cdb_l_idN       <= {TAG{1'b0}};
149         cdb_l_dataN     <= {DATA{1'b0}};
150         disp_bus0N      <= {OP+4*TAG+ADDR{1'b0}};
151         disp_bus1N      <= {OP+4*TAG+ADDR{1'b0}};
152         pcN             <= {PC{1'b0}};
153 
154         alt_op0N        <= {OP{1'b0}};
155         alt_addr0N      <= {ADDR{1'b0}};
156         alt_op1N        <= {OP{1'b0}};
157         alt_addr1N      <= {ADDR{1'b0}};
158 
159         func0_pcN       <= {PC{1'b0}};
160         func0_opN       <= {OP{1'b0}};
161         func0_stallN    <= {TAG{1'b0}};
162         func0_addressN  <= {ADDR{1'b0}};
163         func0_tagN      <= {TAG{1'b0}};
164         func0_dataN     <= {DATA{1'b0}};
165         func1_pcN       <= {PC{1'b0}};
166         func1_opN       <= {OP{1'b0}};
167         func1_stallN    <= {TAG{1'b0}};
168         func1_addressN  <= {ADDR{1'b0}};
169         func1_tagN      <= {TAG{1'b0}};
170         func1_dataN     <= {DATA{1'b0}};
171     end
172     else begin
173         if ( !clk ) begin
174             // Latch buses on negedge to use for logic; propagation is assumed 
175             // to be 1/2 clock cycle
176             cdb_r0_idN      <= cdb_r0_id;
177             cdb_r0_dataN    <= cdb_r0_data;
178             cdb_r1_idN      <= cdb_r1_id;
179             cdb_r1_dataN    <= cdb_r1_data;
180             cdb_r2_idN      <= cdb_r2_id;
181             cdb_r2_dataN    <= cdb_r2_data;
182             cdb_a_idN       <= cdb_a_id;
183             cdb_a_dataN     <= cdb_a_data;
184             cdb_m_idN       <= cdb_m_id;
185             cdb_m_dataN     <= cdb_m_data;
186             cdb_l_idN       <= cdb_l_id;
187             cdb_l_dataN     <= cdb_l_data;
188             disp_bus0N      <= disp_bus0;
189             disp_bus1N      <= disp_bus1;
190             pcN             <= pc;
191 
192             alt_op0N        <= alt_op0;
193             alt_addr0N      <= alt_addr0;
194             alt_op1N        <= alt_op1;
195             alt_addr1N      <= alt_addr1;
196 
197             func0_pcN       <= func0_pc_next;
198             func0_opN       <= func0_op_next;
199             func0_stallN    <= func0_stall_next;
200             func0_addressN  <= func0_address_next;
201             func0_tagN      <= func0_tag_next;
202             func0_dataN     <= func0_data_next;
203             func1_pcN       <= func1_pc_next;
204             func1_opN       <= func1_op_next;
205             func1_stallN    <= func1_stall_next;
206             func1_addressN  <= func1_address_next;
207             func1_tagN      <= func1_tag_next;
208             func1_dataN     <= func1_data_next;
209         end
210     end
211 end
212 
213 always @* begin : LOAD_RS_NEG_LOGIC
214     {disp_rsv0N,
215      disp_op0N,
216      disp_dst0N,
217      disp_src0N,
218      dummy_tagN,
219      disp_addr0N} = disp_bus0N;
220     {disp_rsv1N,
221      disp_op1N,
222      disp_dst1N,
223      disp_src1N,
224      dummy_tagN,
225      disp_addr1N} = disp_bus1N;
226 
227     // Store ops
228     if ( disp_rsv0N == S0 ) begin
229         func0_pc_nextN      = pcN - {{PC-1{1'b0}}, 1'b1};   // Subtract 1 for comparison purposes
230         func0_op_nextN      = disp_op0N;
231         func0_address_nextN = disp_addr0N;
232         func0_tag_tempN     = disp_src0N;
233         func0_loadN = 1'b1;
234     end
235     else if ( disp_rsv1N == S0 ) begin
236         func0_pc_nextN      = pcN;  // No subtraction, previous command is on disp_bus0
237         func0_op_nextN      = disp_op1N;
238         func0_address_nextN = disp_addr1N;
239         func0_tag_tempN     = disp_src1N;
240         func0_loadN = 1'b1;
241     end
242     else begin
243         func0_pc_nextN      = func0_pcN;
244         func0_op_nextN      = func0_opN;
245         func0_address_nextN = func0_addressN;
246         func0_tag_tempN     = func0_tagN;
247         func0_loadN = 1'b0;
248     end
249 
250     if ( disp_rsv0N == S1 ) begin
251         func1_pc_nextN      = pcN - {{PC-1{1'b0}}, 1'b1};
252         func1_op_nextN      = disp_op0N;
253         func1_address_nextN = disp_addr0N;
254         func1_tag_tempN     = disp_src0N;
255         func1_loadN = 1'b1;
256     end
257     else if ( disp_rsv1N == S1 ) begin
258         func1_pc_nextN      = pcN - {{PC-1{1'b0}}, 1'b1};
259         func1_op_nextN      = disp_op1N;
260         func1_address_nextN = disp_addr1N;
261         func1_tag_tempN     = disp_src1N;
262         func1_loadN = 1'b1;
263     end
264     else begin
265         func1_pc_nextN      = func1_pcN;
266         func1_op_nextN      = func1_opN;
267         func1_address_nextN = func1_addressN;
268         func1_tag_tempN     = func1_tagN;
269         func1_loadN = 1'b0;
270     end
271 
272     // Check for stalls
273     if ( func0_loadN && |alt_op0N && alt_addr0N == func0_address_nextN ) begin
274         func0_stall_nextN   = L0;
275     end
276     else if ( func0_loadN && |alt_op1N && alt_addr1N == func0_address_nextN ) begin
277         func0_stall_nextN   = L1;
278     end
279     else if ( cdb_l_idN == func0_stallN ) begin
280         func0_stall_nextN   = {TAG{1'b0}};
281     end
282     else begin
283         func0_stall_nextN   = func0_stallN;
284     end
285 
286     if ( func1_loadN && |alt_op0N && alt_addr0N == func1_address_nextN ) begin
287         func1_stall_nextN   = L0;
288     end
289     else if ( func1_loadN && |alt_op1N && alt_addr1N == func1_address_nextN ) begin
290         func1_stall_nextN   = L1;
291     end
292     else if ( cdb_l_idN == func1_stallN ) begin
293         func1_stall_nextN   = {TAG{1'b0}};
294     end
295     else begin
296         func1_stall_nextN   = func1_stallN;
297     end
298 
299     // SRC1: check temp tags for data on the bus and load if present
300     if ( ~|func0_tag_tempN ) begin
301         func0_tag_nextN  = {TAG{1'b0}};
302         func0_data_nextN = func0_dataN;
303     end
304     else if ( func0_tag_tempN == cdb_r0_idN ) begin
305         func0_tag_nextN  = {TAG{1'b0}};
306         func0_data_nextN = cdb_r0_dataN;
307     end
308     else if ( func0_tag_tempN == cdb_r1_idN ) begin
309         func0_tag_nextN  = {TAG{1'b0}};
310         func0_data_nextN = cdb_r1_dataN;
311     end
312     else if ( func0_tag_tempN == cdb_r2_idN ) begin
313         func0_tag_nextN  = {TAG{1'b0}};
314         func0_data_nextN = cdb_r2_dataN;
315     end
316     else if ( func0_tag_tempN == cdb_a_idN ) begin
317         func0_tag_nextN  = {TAG{1'b0}};
318         func0_data_nextN = cdb_a_dataN;
319     end
320     else if ( func0_tag_tempN == cdb_m_idN ) begin
321         func0_tag_nextN  = {TAG{1'b0}};
322         func0_data_nextN = cdb_m_dataN;
323     end
324     else if ( func0_tag_tempN == cdb_l_idN ) begin
325         func0_tag_nextN  = {TAG{1'b0}};
326         func0_data_nextN = cdb_l_dataN;
327     end
328     else begin
329         // save temp tag and zero data if not available
330         func0_tag_nextN  = func0_tag_tempN;
331         func0_data_nextN = {DATA{1'b0}};
332     end
333 
334     // SRC2: check temp tags for data on the bus and load if present
335     if ( ~|func1_tag_tempN ) begin
336         func1_tag_nextN  = {TAG{1'b0}};
337         func1_data_nextN = func1_dataN;
338     end
339     else if ( func1_tag_tempN == cdb_r0_idN ) begin
340         func1_tag_nextN  = {TAG{1'b0}};
341         func1_data_nextN = cdb_r0_dataN;
342     end
343     else if ( func1_tag_tempN == cdb_r1_idN ) begin
344         func1_tag_nextN  = {TAG{1'b0}};
345         func1_data_nextN = cdb_r1_dataN;
346     end
347     else if ( func1_tag_tempN == cdb_r2_idN ) begin
348         func1_tag_nextN  = {TAG{1'b0}};
349         func1_data_nextN = cdb_r2_dataN;
350     end
351     else if ( func1_tag_tempN == cdb_a_idN ) begin
352         func1_tag_nextN  = {TAG{1'b0}};
353         func1_data_nextN = cdb_a_dataN;
354     end
355     else if ( func1_tag_tempN == cdb_m_idN ) begin
356         func1_tag_nextN  = {TAG{1'b0}};
357         func1_data_nextN = cdb_m_dataN;
358     end
359     else if ( func1_tag_tempN == cdb_l_idN ) begin
360         func1_tag_nextN  = {TAG{1'b0}};
361         func1_data_nextN = cdb_l_dataN;
362     end
363     else begin
364         // save temp tag and zero data if not available
365         func1_tag_nextN  = func1_tag_tempN;
366         func1_data_nextN = {DATA{1'b0}};
367     end
368 
369     func_val_nextN[0]   = |func0_op_nextN && ~|func0_stall_nextN && ~|func0_tag_nextN;
370     func_val_nextN[1]   = |func1_op_nextN && ~|func1_stall_nextN && ~|func1_tag_nextN;
371 end
372 
373 always @* begin : LOAD_RS_POS_LATCH
374     if ( !rstn ) begin
375         func_val        <= 2'b00;
376         func0_pc        <= {PC{1'b0}};
377         func0_op        <= {OP{1'b0}};
378         func0_stall     <= {TAG{1'b0}};
379         func0_address   <= {ADDR{1'b0}};
380         func0_tag       <= {TAG{1'b0}};
381         func0_data      <= {DATA{1'b0}};
382         func1_pc        <= {PC{1'b0}};
383         func1_op        <= {OP{1'b0}};
384         func1_stall     <= {TAG{1'b0}};
385         func1_address   <= {ADDR{1'b0}};
386         func1_tag       <= {TAG{1'b0}};
387         func1_data      <= {DATA{1'b0}};
388     end
389     else begin
390         if ( clk ) begin
391             func_val        <= func_val_nextN;
392             func0_pc        <= func0_pc_nextN;
393             func0_op        <= func0_op_nextN;
394             func0_stall     <= func0_stall_nextN;
395             func0_address   <= func0_address_nextN;
396             func0_tag       <= func0_tag_nextN;
397             func0_data      <= func0_data_nextN;
398             func1_pc        <= func1_pc_nextN;
399             func1_op        <= func1_op_nextN;
400             func1_stall     <= func1_stall_nextN;
401             func1_address   <= func1_address_nextN;
402             func1_tag       <= func0_tag_nextN;
403             func1_data      <= func0_data_nextN;
404         end
405     end
406 end
407 
408 endmodule
409