1 |
221 |
olivier.gi |
// (C) 2001-2014 Altera Corporation. All rights reserved.
|
2 |
|
|
// Your use of Altera Corporation's design tools, logic functions and other
|
3 |
|
|
// software and tools, and its AMPP partner logic functions, and any output
|
4 |
|
|
// files any of the foregoing (including device programming or simulation
|
5 |
|
|
// files), and any associated documentation or information are expressly subject
|
6 |
|
|
// to the terms and conditions of the Altera Program License Subscription
|
7 |
|
|
// Agreement, Altera MegaCore Function License Agreement, or other applicable
|
8 |
|
|
// license agreement, including, without limitation, that your use is for the
|
9 |
|
|
// sole purpose of programming logic devices manufactured by Altera and sold by
|
10 |
|
|
// Altera or its authorized distributors. Please refer to the applicable
|
11 |
|
|
// agreement for further details.
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
// $Id: //acds/rel/14.0/ip/merlin/altera_merlin_multiplexer/altera_merlin_multiplexer.sv.terp#1 $
|
15 |
|
|
// $Revision: #1 $
|
16 |
|
|
// $Date: 2014/02/16 $
|
17 |
|
|
// $Author: swbranch $
|
18 |
|
|
|
19 |
|
|
// ------------------------------------------
|
20 |
|
|
// Merlin Multiplexer
|
21 |
|
|
// ------------------------------------------
|
22 |
|
|
|
23 |
|
|
`timescale 1 ns / 1 ns
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
// ------------------------------------------
|
27 |
|
|
// Generation parameters:
|
28 |
|
|
// output_name: DE0_NANO_SOC_QSYS_mm_interconnect_0_rsp_mux
|
29 |
|
|
// NUM_INPUTS: 2
|
30 |
|
|
// ARBITRATION_SHARES: 1 1
|
31 |
|
|
// ARBITRATION_SCHEME "no-arb"
|
32 |
|
|
// PIPELINE_ARB: 0
|
33 |
|
|
// PKT_TRANS_LOCK: 60 (arbitration locking enabled)
|
34 |
|
|
// ST_DATA_W: 96
|
35 |
|
|
// ST_CHANNEL_W: 6
|
36 |
|
|
// ------------------------------------------
|
37 |
|
|
|
38 |
|
|
module DE0_NANO_SOC_QSYS_mm_interconnect_0_rsp_mux
|
39 |
|
|
(
|
40 |
|
|
// ----------------------
|
41 |
|
|
// Sinks
|
42 |
|
|
// ----------------------
|
43 |
|
|
input sink0_valid,
|
44 |
|
|
input [96-1 : 0] sink0_data,
|
45 |
|
|
input [6-1: 0] sink0_channel,
|
46 |
|
|
input sink0_startofpacket,
|
47 |
|
|
input sink0_endofpacket,
|
48 |
|
|
output sink0_ready,
|
49 |
|
|
|
50 |
|
|
input sink1_valid,
|
51 |
|
|
input [96-1 : 0] sink1_data,
|
52 |
|
|
input [6-1: 0] sink1_channel,
|
53 |
|
|
input sink1_startofpacket,
|
54 |
|
|
input sink1_endofpacket,
|
55 |
|
|
output sink1_ready,
|
56 |
|
|
|
57 |
|
|
|
58 |
|
|
// ----------------------
|
59 |
|
|
// Source
|
60 |
|
|
// ----------------------
|
61 |
|
|
output src_valid,
|
62 |
|
|
output [96-1 : 0] src_data,
|
63 |
|
|
output [6-1 : 0] src_channel,
|
64 |
|
|
output src_startofpacket,
|
65 |
|
|
output src_endofpacket,
|
66 |
|
|
input src_ready,
|
67 |
|
|
|
68 |
|
|
// ----------------------
|
69 |
|
|
// Clock & Reset
|
70 |
|
|
// ----------------------
|
71 |
|
|
input clk,
|
72 |
|
|
input reset
|
73 |
|
|
);
|
74 |
|
|
localparam PAYLOAD_W = 96 + 6 + 2;
|
75 |
|
|
localparam NUM_INPUTS = 2;
|
76 |
|
|
localparam SHARE_COUNTER_W = 1;
|
77 |
|
|
localparam PIPELINE_ARB = 0;
|
78 |
|
|
localparam ST_DATA_W = 96;
|
79 |
|
|
localparam ST_CHANNEL_W = 6;
|
80 |
|
|
localparam PKT_TRANS_LOCK = 60;
|
81 |
|
|
|
82 |
|
|
// ------------------------------------------
|
83 |
|
|
// Signals
|
84 |
|
|
// ------------------------------------------
|
85 |
|
|
wire [NUM_INPUTS - 1 : 0] request;
|
86 |
|
|
wire [NUM_INPUTS - 1 : 0] valid;
|
87 |
|
|
wire [NUM_INPUTS - 1 : 0] grant;
|
88 |
|
|
wire [NUM_INPUTS - 1 : 0] next_grant;
|
89 |
|
|
reg [NUM_INPUTS - 1 : 0] saved_grant;
|
90 |
|
|
reg [PAYLOAD_W - 1 : 0] src_payload;
|
91 |
|
|
wire last_cycle;
|
92 |
|
|
reg packet_in_progress;
|
93 |
|
|
reg update_grant;
|
94 |
|
|
|
95 |
|
|
wire [PAYLOAD_W - 1 : 0] sink0_payload;
|
96 |
|
|
wire [PAYLOAD_W - 1 : 0] sink1_payload;
|
97 |
|
|
|
98 |
|
|
assign valid[0] = sink0_valid;
|
99 |
|
|
assign valid[1] = sink1_valid;
|
100 |
|
|
|
101 |
|
|
|
102 |
|
|
// ------------------------------------------
|
103 |
|
|
// ------------------------------------------
|
104 |
|
|
// Grant Logic & Updates
|
105 |
|
|
// ------------------------------------------
|
106 |
|
|
// ------------------------------------------
|
107 |
|
|
reg [NUM_INPUTS - 1 : 0] lock;
|
108 |
|
|
always @* begin
|
109 |
|
|
lock[0] = sink0_data[60];
|
110 |
|
|
lock[1] = sink1_data[60];
|
111 |
|
|
end
|
112 |
|
|
|
113 |
|
|
assign last_cycle = src_valid & src_ready & src_endofpacket & ~(|(lock & grant));
|
114 |
|
|
|
115 |
|
|
// ------------------------------------------
|
116 |
|
|
// We're working on a packet at any time valid is high, except
|
117 |
|
|
// when this is the endofpacket.
|
118 |
|
|
// ------------------------------------------
|
119 |
|
|
always @(posedge clk or posedge reset) begin
|
120 |
|
|
if (reset) begin
|
121 |
|
|
packet_in_progress <= 1'b0;
|
122 |
|
|
end
|
123 |
|
|
else begin
|
124 |
|
|
if (last_cycle)
|
125 |
|
|
packet_in_progress <= 1'b0;
|
126 |
|
|
else if (src_valid)
|
127 |
|
|
packet_in_progress <= 1'b1;
|
128 |
|
|
end
|
129 |
|
|
end
|
130 |
|
|
|
131 |
|
|
|
132 |
|
|
// ------------------------------------------
|
133 |
|
|
// Shares
|
134 |
|
|
//
|
135 |
|
|
// Special case: all-equal shares _should_ be optimized into assigning a
|
136 |
|
|
// constant to next_grant_share.
|
137 |
|
|
// Special case: all-1's shares _should_ result in the share counter
|
138 |
|
|
// being optimized away.
|
139 |
|
|
// ------------------------------------------
|
140 |
|
|
// Input | arb shares | counter load value
|
141 |
|
|
// 0 | 1 | 0
|
142 |
|
|
// 1 | 1 | 0
|
143 |
|
|
wire [SHARE_COUNTER_W - 1 : 0] share_0 = 1'd0;
|
144 |
|
|
wire [SHARE_COUNTER_W - 1 : 0] share_1 = 1'd0;
|
145 |
|
|
|
146 |
|
|
// ------------------------------------------
|
147 |
|
|
// Choose the share value corresponding to the grant.
|
148 |
|
|
// ------------------------------------------
|
149 |
|
|
reg [SHARE_COUNTER_W - 1 : 0] next_grant_share;
|
150 |
|
|
always @* begin
|
151 |
|
|
next_grant_share =
|
152 |
|
|
share_0 & { SHARE_COUNTER_W {next_grant[0]} } |
|
153 |
|
|
share_1 & { SHARE_COUNTER_W {next_grant[1]} };
|
154 |
|
|
end
|
155 |
|
|
|
156 |
|
|
// ------------------------------------------
|
157 |
|
|
// Flag to indicate first packet of an arb sequence.
|
158 |
|
|
// ------------------------------------------
|
159 |
|
|
wire grant_changed = ~packet_in_progress && ~(|(saved_grant & valid));
|
160 |
|
|
reg first_packet_r;
|
161 |
|
|
wire first_packet = grant_changed | first_packet_r;
|
162 |
|
|
always @(posedge clk or posedge reset) begin
|
163 |
|
|
if (reset) begin
|
164 |
|
|
first_packet_r <= 1'b0;
|
165 |
|
|
end
|
166 |
|
|
else begin
|
167 |
|
|
if (update_grant)
|
168 |
|
|
first_packet_r <= 1'b1;
|
169 |
|
|
else if (last_cycle)
|
170 |
|
|
first_packet_r <= 1'b0;
|
171 |
|
|
else if (grant_changed)
|
172 |
|
|
first_packet_r <= 1'b1;
|
173 |
|
|
end
|
174 |
|
|
end
|
175 |
|
|
|
176 |
|
|
// ------------------------------------------
|
177 |
|
|
// Compute the next share-count value.
|
178 |
|
|
// ------------------------------------------
|
179 |
|
|
reg [SHARE_COUNTER_W - 1 : 0] p1_share_count;
|
180 |
|
|
reg [SHARE_COUNTER_W - 1 : 0] share_count;
|
181 |
|
|
reg share_count_zero_flag;
|
182 |
|
|
|
183 |
|
|
always @* begin
|
184 |
|
|
if (first_packet) begin
|
185 |
|
|
p1_share_count = next_grant_share;
|
186 |
|
|
end
|
187 |
|
|
else begin
|
188 |
|
|
// Update the counter, but don't decrement below 0.
|
189 |
|
|
p1_share_count = share_count_zero_flag ? '0 : share_count - 1'b1;
|
190 |
|
|
end
|
191 |
|
|
end
|
192 |
|
|
|
193 |
|
|
// ------------------------------------------
|
194 |
|
|
// Update the share counter and share-counter=zero flag.
|
195 |
|
|
// ------------------------------------------
|
196 |
|
|
always @(posedge clk or posedge reset) begin
|
197 |
|
|
if (reset) begin
|
198 |
|
|
share_count <= '0;
|
199 |
|
|
share_count_zero_flag <= 1'b1;
|
200 |
|
|
end
|
201 |
|
|
else begin
|
202 |
|
|
if (last_cycle) begin
|
203 |
|
|
share_count <= p1_share_count;
|
204 |
|
|
share_count_zero_flag <= (p1_share_count == '0);
|
205 |
|
|
end
|
206 |
|
|
end
|
207 |
|
|
end
|
208 |
|
|
|
209 |
|
|
// ------------------------------------------
|
210 |
|
|
// For each input, maintain a final_packet signal which goes active for the
|
211 |
|
|
// last packet of a full-share packet sequence. Example: if I have 4
|
212 |
|
|
// shares and I'm continuously requesting, final_packet is active in the
|
213 |
|
|
// 4th packet.
|
214 |
|
|
// ------------------------------------------
|
215 |
|
|
wire final_packet_0 = 1'b1;
|
216 |
|
|
|
217 |
|
|
wire final_packet_1 = 1'b1;
|
218 |
|
|
|
219 |
|
|
|
220 |
|
|
// ------------------------------------------
|
221 |
|
|
// Concatenate all final_packet signals (wire or reg) into a handy vector.
|
222 |
|
|
// ------------------------------------------
|
223 |
|
|
wire [NUM_INPUTS - 1 : 0] final_packet = {
|
224 |
|
|
final_packet_1,
|
225 |
|
|
final_packet_0
|
226 |
|
|
};
|
227 |
|
|
|
228 |
|
|
// ------------------------------------------
|
229 |
|
|
// ------------------------------------------
|
230 |
|
|
wire p1_done = |(final_packet & grant);
|
231 |
|
|
|
232 |
|
|
// ------------------------------------------
|
233 |
|
|
// Flag for the first cycle of packets within an
|
234 |
|
|
// arb sequence
|
235 |
|
|
// ------------------------------------------
|
236 |
|
|
reg first_cycle;
|
237 |
|
|
always @(posedge clk, posedge reset) begin
|
238 |
|
|
if (reset)
|
239 |
|
|
first_cycle <= 0;
|
240 |
|
|
else
|
241 |
|
|
first_cycle <= last_cycle && ~p1_done;
|
242 |
|
|
end
|
243 |
|
|
|
244 |
|
|
|
245 |
|
|
always @* begin
|
246 |
|
|
update_grant = 0;
|
247 |
|
|
|
248 |
|
|
// ------------------------------------------
|
249 |
|
|
// No arbitration pipeline, update grant whenever
|
250 |
|
|
// the current arb winner has consumed all shares,
|
251 |
|
|
// or all requests are low
|
252 |
|
|
// ------------------------------------------
|
253 |
|
|
update_grant = (last_cycle && p1_done) || (first_cycle && ~(|valid));
|
254 |
|
|
update_grant = last_cycle;
|
255 |
|
|
end
|
256 |
|
|
|
257 |
|
|
wire save_grant;
|
258 |
|
|
assign save_grant = 1;
|
259 |
|
|
assign grant = next_grant;
|
260 |
|
|
|
261 |
|
|
always @(posedge clk, posedge reset) begin
|
262 |
|
|
if (reset)
|
263 |
|
|
saved_grant <= '0;
|
264 |
|
|
else if (save_grant)
|
265 |
|
|
saved_grant <= next_grant;
|
266 |
|
|
end
|
267 |
|
|
|
268 |
|
|
// ------------------------------------------
|
269 |
|
|
// ------------------------------------------
|
270 |
|
|
// Arbitrator
|
271 |
|
|
// ------------------------------------------
|
272 |
|
|
// ------------------------------------------
|
273 |
|
|
|
274 |
|
|
// ------------------------------------------
|
275 |
|
|
// Create a request vector that stays high during
|
276 |
|
|
// the packet for unpipelined arbitration.
|
277 |
|
|
//
|
278 |
|
|
// The pipelined arbitration scheme does not require
|
279 |
|
|
// request to be held high during the packet.
|
280 |
|
|
// ------------------------------------------
|
281 |
|
|
assign request = valid;
|
282 |
|
|
|
283 |
|
|
|
284 |
|
|
altera_merlin_arbitrator
|
285 |
|
|
#(
|
286 |
|
|
.NUM_REQUESTERS(NUM_INPUTS),
|
287 |
|
|
.SCHEME ("no-arb"),
|
288 |
|
|
.PIPELINE (0)
|
289 |
|
|
) arb (
|
290 |
|
|
.clk (clk),
|
291 |
|
|
.reset (reset),
|
292 |
|
|
.request (request),
|
293 |
|
|
.grant (next_grant),
|
294 |
|
|
.save_top_priority (src_valid),
|
295 |
|
|
.increment_top_priority (update_grant)
|
296 |
|
|
);
|
297 |
|
|
|
298 |
|
|
// ------------------------------------------
|
299 |
|
|
// ------------------------------------------
|
300 |
|
|
// Mux
|
301 |
|
|
//
|
302 |
|
|
// Implemented as a sum of products.
|
303 |
|
|
// ------------------------------------------
|
304 |
|
|
// ------------------------------------------
|
305 |
|
|
|
306 |
|
|
assign sink0_ready = src_ready && grant[0];
|
307 |
|
|
assign sink1_ready = src_ready && grant[1];
|
308 |
|
|
|
309 |
|
|
assign src_valid = |(grant & valid);
|
310 |
|
|
|
311 |
|
|
always @* begin
|
312 |
|
|
src_payload =
|
313 |
|
|
sink0_payload & {PAYLOAD_W {grant[0]} } |
|
314 |
|
|
sink1_payload & {PAYLOAD_W {grant[1]} };
|
315 |
|
|
end
|
316 |
|
|
|
317 |
|
|
// ------------------------------------------
|
318 |
|
|
// Mux Payload Mapping
|
319 |
|
|
// ------------------------------------------
|
320 |
|
|
|
321 |
|
|
assign sink0_payload = {sink0_channel,sink0_data,
|
322 |
|
|
sink0_startofpacket,sink0_endofpacket};
|
323 |
|
|
assign sink1_payload = {sink1_channel,sink1_data,
|
324 |
|
|
sink1_startofpacket,sink1_endofpacket};
|
325 |
|
|
|
326 |
|
|
assign {src_channel,src_data,src_startofpacket,src_endofpacket} = src_payload;
|
327 |
|
|
endmodule
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
|