1 /******************************************************************************
  2 * Copyright 2013, Hectic Tech (Jeff Heckey). All rights reserved
  3 ******************************************************************************/
  4 
  5 module load_rs #(
  6     parameter TAG = 4,    // Tag size
  7     parameter OP  = 3,    // OPCODE size
  8     parameter ADDR = 32   // Address width
  9 ) (
 10     input  wire                     clk,
 11     input  wire                     rstn,
 12 
 13     input  wire [TAG-1:0]           cdb_s_id,
 14     input  wire [OP+4*TAG+ADDR-1:0] disp_bus0,
 15     input  wire [OP+4*TAG+ADDR-1:0] disp_bus1,
 16 
 17     input  wire [OP-1:0]            alt_op0,
 18     input  wire [ADDR-1:0]          alt_addr0,
 19     input  wire [OP-1:0]            alt_op1,
 20     input  wire [ADDR-1:0]          alt_addr1,
 21 
 22     output reg  [1:0]               func_val,
 23     input  wire [1:0]               func_ack,
 24     output reg  [OP-1:0]            func0_op,
 25     output reg  [TAG-1:0]           func0_stall,
 26     output reg  [ADDR-1:0]          func0_address,
 27     output reg  [OP-1:0]            func1_op,
 28     output reg  [TAG-1:0]           func1_stall,
 29     output reg  [ADDR-1:0]          func1_address
 30 );
 31 
 32 localparam L0 = 4'd12,
 33            L1 = 4'd13,
 34            S0 = 4'd14,
 35            S1 = 4'd15;
 36 
 37 reg  [TAG-1:0]              cdb_s_idN;
 38 reg  [OP+4*TAG+ADDR-1:0]    disp_bus0N;
 39 reg  [OP+4*TAG+ADDR-1:0]    disp_bus1N;
 40 reg  [TAG-1:0]              disp_rsv0N;
 41 reg  [OP-1:0]               disp_op0N;
 42 reg  [TAG-1:0]              disp_dst0N;
 43 reg  [ADDR-1:0]             disp_addr0N;
 44 reg  [TAG-1:0]              disp_rsv1N;
 45 reg  [OP-1:0]               disp_op1N;
 46 reg  [TAG-1:0]              disp_dst1N;
 47 reg  [ADDR-1:0]             disp_addr1N;
 48 reg  [OP-1:0]               alt_op0N;
 49 reg  [ADDR-1:0]             alt_addr0N;
 50 reg  [OP-1:0]               alt_op1N;
 51 reg  [ADDR-1:0]             alt_addr1N;
 52 reg  [TAG-1:0]              dummy0_tagN, dummy1_tagN;
 53 reg  [1:0]                  func_val_nextN;
 54 reg                         func0_loadN, func1_loadN;
 55 reg  [OP-1:0]               func0_opN, func0_op_nextN, func0_op_next;
 56 reg  [TAG-1:0]              func0_stallN, func0_stall_nextN, func0_stall_next;
 57 reg  [ADDR-1:0]             func0_addressN, func0_address_nextN, func0_address_next;
 58 reg  [OP-1:0]               func1_opN, func1_op_nextN, func1_op_next;
 59 reg  [TAG-1:0]              func1_stallN, func1_stall_nextN, func1_stall_next;
 60 reg  [ADDR-1:0]             func1_addressN, func1_address_nextN, func1_address_next;
 61 
 62 always @* begin : LOAD_RS_POS_LOGIC
 63     if ( func_ack[0] && |func0_op ) begin
 64         func0_op_next       = {OP{1'b0}};
 65         func0_stall_next    = {TAG{1'b0}};
 66         func0_address_next  = {ADDR{1'b0}};
 67     end
 68     else begin
 69         func0_op_next       = func0_op;
 70         func0_stall_next    = func0_stall;
 71         func0_address_next  = func0_address;
 72     end
 73 
 74     if ( func_ack[1] && |func1_op ) begin
 75         func1_op_next       = {OP{1'b0}};
 76         func1_stall_next    = {TAG{1'b0}};
 77         func1_address_next  = {ADDR{1'b0}};
 78     end
 79     else begin
 80         func1_op_next       = func1_op;
 81         func1_stall_next    = func1_stall;
 82         func1_address_next  = func1_address;
 83     end
 84 end
 85 
 86 always @* begin : LOAD_RS_NEG_LATCHES
 87     if ( !rstn ) begin
 88         cdb_s_idN       <= {TAG{1'b0}};
 89         disp_bus0N      <= {OP+4*TAG{1'b0}};
 90         disp_bus1N      <= {OP+4*TAG{1'b0}};
 91 
 92         alt_op0N        <= {OP{1'b0}};
 93         alt_addr0N      <= {ADDR{1'b0}};
 94         alt_op1N        <= {OP{1'b0}};
 95         alt_addr1N      <= {ADDR{1'b0}};
 96 
 97         func0_opN       <= {OP{1'b0}};
 98         func0_stallN    <= {TAG{1'b0}};
 99         func0_addressN  <= {ADDR{1'b0}};
100         func1_opN       <= {OP{1'b0}};
101         func1_stallN    <= {TAG{1'b0}};
102         func1_addressN  <= {ADDR{1'b0}};
103     end
104     else begin
105         if ( !clk ) begin
106             // Latch buses on negedge to use for logic; propagation is assumed 
107             // to be 1/2 clock cycle
108             cdb_s_idN       <= cdb_s_id;
109             disp_bus0N      <= disp_bus0;
110             disp_bus1N      <= disp_bus1;
111 
112             alt_op0N        <= alt_op0;
113             alt_addr0N      <= alt_addr0;
114             alt_op1N        <= alt_op1;
115             alt_addr1N      <= alt_addr1;
116 
117             func0_opN       <= func0_op_next;
118             func0_stallN    <= func0_stall_next;
119             func0_addressN  <= func0_address_next;
120             func1_opN       <= func1_op_next;
121             func1_stallN    <= func1_stall_next;
122             func1_addressN  <= func1_address_next;
123         end
124     end
125 end
126 
127 always @* begin : LOAD_RS_NEG_LOGIC
128     {disp_rsv0N,
129      disp_op0N,
130      disp_dst0N,
131      dummy0_tagN,   // unused tags
132      dummy1_tagN,
133      disp_addr0N} = disp_bus0N;
134     {disp_rsv1N,
135      disp_op1N,
136      disp_dst1N,
137      dummy0_tagN,
138      dummy1_tagN,
139      disp_addr1N} = disp_bus1N;
140 
141     // Load ops
142     if ( disp_rsv0N == L0 ) begin
143         func0_op_nextN      = disp_op0N;
144         func0_address_nextN = disp_addr0N;
145         func0_loadN = 1'b1;
146     end
147     else if ( disp_rsv1N == L0 ) begin
148         func0_op_nextN      = disp_op1N;
149         func0_address_nextN = disp_addr1N;
150         func0_loadN = 1'b1;
151     end
152     else begin
153         func0_op_nextN      = func0_opN;
154         func0_address_nextN = func0_addressN;
155         func0_loadN = 1'b0;
156     end
157 
158     if ( disp_rsv0N == L1 ) begin
159         func1_op_nextN      = disp_op0N;
160         func1_address_nextN = disp_addr0N;
161         func1_loadN = 1'b1;
162     end
163     else if ( disp_rsv1N == L1 ) begin
164         func1_op_nextN      = disp_op1N;
165         func1_address_nextN = disp_addr1N;
166         func1_loadN = 1'b1;
167     end
168     else begin
169         func1_op_nextN      = func1_opN;
170         func1_address_nextN = func1_addressN;
171         func1_loadN = 1'b0;
172     end
173 
174     // Check for stalls
175     if ( func0_loadN && |alt_op0N && alt_addr0N == func0_address_nextN ) begin
176         func0_stall_nextN   = S0;
177     end
178     else if ( func0_loadN && |alt_op1N && alt_addr1N == func0_address_nextN ) begin
179         func0_stall_nextN   = S1;
180     end
181     else if ( cdb_s_idN == func0_stallN ) begin
182         func0_stall_nextN   = {TAG{1'b0}};
183     end
184     else begin
185         func0_stall_nextN   = func0_stallN;
186     end
187 
188     if ( func1_loadN && |alt_op0N && alt_addr0N == func1_address_nextN ) begin
189         func1_stall_nextN   = S0;
190     end
191     else if ( func1_loadN && |alt_op1N && alt_addr1N == func1_address_nextN ) begin
192         func1_stall_nextN   = S1;
193     end
194     else if ( cdb_s_idN == func1_stallN ) begin
195         func1_stall_nextN   = {TAG{1'b0}};
196     end
197     else begin
198         func1_stall_nextN   = func1_stallN;
199     end
200 
201     func_val_nextN[0]   = |func0_op_nextN && ~|func0_stall_nextN;
202     func_val_nextN[1]   = |func1_op_nextN && ~|func1_stall_nextN;
203 end
204 
205 always @* begin : LOAD_RS_POS_LATCH
206     if ( !rstn ) begin
207         func_val        <= 2'b00;
208         func0_op        <= {OP{1'b0}};
209         func0_stall     <= {TAG{1'b0}};
210         func0_address   <= {ADDR{1'b0}};
211         func1_op        <= {OP{1'b0}};
212         func1_stall     <= {TAG{1'b0}};
213         func1_address   <= {ADDR{1'b0}};
214     end
215     else begin
216         if ( clk ) begin
217             func_val        <= func_val_nextN;
218             func0_op        <= func0_op_nextN;
219             func0_stall     <= func0_stall_nextN;
220             func0_address   <= func0_address_nextN;
221             func1_op        <= func1_op_nextN;
222             func1_stall     <= func1_stall_nextN;
223             func1_address   <= func1_address_nextN;
224         end
225     end
226 end
227 
228 endmodule
229