// (C) 2001-2017 Intel Corporation. All rights reserved.
|
// (C) 2001-2017 Intel Corporation. All rights reserved.
|
// Your use of Intel Corporation's design tools, logic functions and other
|
// Your use of Intel Corporation's design tools, logic functions and other
|
// software and tools, and its AMPP partner logic functions, and any output
|
// software and tools, and its AMPP partner logic functions, and any output
|
// files any of the foregoing (including device programming or simulation
|
// files from any of the foregoing (including device programming or simulation
|
// files), and any associated documentation or information are expressly subject
|
// files), and any associated documentation or information are expressly subject
|
// to the terms and conditions of the Intel Program License Subscription
|
// to the terms and conditions of the Intel Program License Subscription
|
// Agreement, Intel MegaCore Function License Agreement, or other applicable
|
// Agreement, Intel FPGA IP License Agreement, or other applicable
|
// license agreement, including, without limitation, that your use is for the
|
// license agreement, including, without limitation, that your use is for the
|
// sole purpose of programming logic devices manufactured by Intel and sold by
|
// sole purpose of programming logic devices manufactured by Intel and sold by
|
// Intel or its authorized distributors. Please refer to the applicable
|
// Intel or its authorized distributors. Please refer to the applicable
|
// agreement for further details.
|
// agreement for further details.
|
|
|
|
|
// (C) 2001-2014 Altera Corporation. All rights reserved.
|
// (C) 2001-2014 Altera Corporation. All rights reserved.
|
// Your use of Altera Corporation's design tools, logic functions and other
|
// Your use of Altera Corporation's design tools, logic functions and other
|
// software and tools, and its AMPP partner logic functions, and any output
|
// software and tools, and its AMPP partner logic functions, and any output
|
// files any of the foregoing (including device programming or simulation
|
// files any of the foregoing (including device programming or simulation
|
// files), and any associated documentation or information are expressly subject
|
// files), and any associated documentation or information are expressly subject
|
// to the terms and conditions of the Altera Program License Subscription
|
// to the terms and conditions of the Altera Program License Subscription
|
// Agreement, Altera MegaCore Function License Agreement, or other applicable
|
// Agreement, Altera MegaCore Function License Agreement, or other applicable
|
// license agreement, including, without limitation, that your use is for the
|
// license agreement, including, without limitation, that your use is for the
|
// sole purpose of programming logic devices manufactured by Altera and sold by
|
// sole purpose of programming logic devices manufactured by Altera and sold by
|
// Altera or its authorized distributors. Please refer to the applicable
|
// Altera or its authorized distributors. Please refer to the applicable
|
// agreement for further details.
|
// agreement for further details.
|
|
|
|
|
// $Id: //acds/rel/17.0std/ip/merlin/altera_merlin_multiplexer/altera_merlin_multiplexer.sv.terp#1 $
|
// $Id: //acds/rel/17.1std/ip/merlin/altera_merlin_multiplexer/altera_merlin_multiplexer.sv.terp#1 $
|
// $Revision: #1 $
|
// $Revision: #1 $
|
// $Date: 2017/01/22 $
|
// $Date: 2017/07/30 $
|
// $Author: swbranch $
|
// $Author: swbranch $
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Merlin Multiplexer
|
// Merlin Multiplexer
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
`timescale 1 ns / 1 ns
|
`timescale 1 ns / 1 ns
|
|
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Generation parameters:
|
// Generation parameters:
|
// output_name: ulight_fifo_mm_interconnect_0_cmd_mux
|
// output_name: ulight_fifo_mm_interconnect_0_cmd_mux
|
// NUM_INPUTS: 2
|
// NUM_INPUTS: 2
|
// ARBITRATION_SHARES: 1 1
|
// ARBITRATION_SHARES: 1 1
|
// ARBITRATION_SCHEME "round-robin"
|
// ARBITRATION_SCHEME "round-robin"
|
// PIPELINE_ARB: 1
|
// PIPELINE_ARB: 1
|
// PKT_TRANS_LOCK: 70 (arbitration locking enabled)
|
// PKT_TRANS_LOCK: 70 (arbitration locking enabled)
|
// ST_DATA_W: 129
|
// ST_DATA_W: 129
|
// ST_CHANNEL_W: 22
|
// ST_CHANNEL_W: 22
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
module ulight_fifo_mm_interconnect_0_cmd_mux
|
module ulight_fifo_mm_interconnect_0_cmd_mux
|
(
|
(
|
// ----------------------
|
// ----------------------
|
// Sinks
|
// Sinks
|
// ----------------------
|
// ----------------------
|
input sink0_valid,
|
input sink0_valid,
|
input [129-1 : 0] sink0_data,
|
input [129-1 : 0] sink0_data,
|
input [22-1: 0] sink0_channel,
|
input [22-1: 0] sink0_channel,
|
input sink0_startofpacket,
|
input sink0_startofpacket,
|
input sink0_endofpacket,
|
input sink0_endofpacket,
|
output sink0_ready,
|
output sink0_ready,
|
|
|
input sink1_valid,
|
input sink1_valid,
|
input [129-1 : 0] sink1_data,
|
input [129-1 : 0] sink1_data,
|
input [22-1: 0] sink1_channel,
|
input [22-1: 0] sink1_channel,
|
input sink1_startofpacket,
|
input sink1_startofpacket,
|
input sink1_endofpacket,
|
input sink1_endofpacket,
|
output sink1_ready,
|
output sink1_ready,
|
|
|
|
|
// ----------------------
|
// ----------------------
|
// Source
|
// Source
|
// ----------------------
|
// ----------------------
|
output src_valid,
|
output src_valid,
|
output [129-1 : 0] src_data,
|
output [129-1 : 0] src_data,
|
output [22-1 : 0] src_channel,
|
output [22-1 : 0] src_channel,
|
output src_startofpacket,
|
output src_startofpacket,
|
output src_endofpacket,
|
output src_endofpacket,
|
input src_ready,
|
input src_ready,
|
|
|
// ----------------------
|
// ----------------------
|
// Clock & Reset
|
// Clock & Reset
|
// ----------------------
|
// ----------------------
|
input clk,
|
input clk,
|
input reset
|
input reset
|
);
|
);
|
localparam PAYLOAD_W = 129 + 22 + 2;
|
localparam PAYLOAD_W = 129 + 22 + 2;
|
localparam NUM_INPUTS = 2;
|
localparam NUM_INPUTS = 2;
|
localparam SHARE_COUNTER_W = 1;
|
localparam SHARE_COUNTER_W = 1;
|
localparam PIPELINE_ARB = 1;
|
localparam PIPELINE_ARB = 1;
|
localparam ST_DATA_W = 129;
|
localparam ST_DATA_W = 129;
|
localparam ST_CHANNEL_W = 22;
|
localparam ST_CHANNEL_W = 22;
|
localparam PKT_TRANS_LOCK = 70;
|
localparam PKT_TRANS_LOCK = 70;
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Signals
|
// Signals
|
// ------------------------------------------
|
// ------------------------------------------
|
wire [NUM_INPUTS - 1 : 0] request;
|
wire [NUM_INPUTS - 1 : 0] request;
|
wire [NUM_INPUTS - 1 : 0] valid;
|
wire [NUM_INPUTS - 1 : 0] valid;
|
wire [NUM_INPUTS - 1 : 0] grant;
|
wire [NUM_INPUTS - 1 : 0] grant;
|
wire [NUM_INPUTS - 1 : 0] next_grant;
|
wire [NUM_INPUTS - 1 : 0] next_grant;
|
reg [NUM_INPUTS - 1 : 0] saved_grant;
|
reg [NUM_INPUTS - 1 : 0] saved_grant;
|
reg [PAYLOAD_W - 1 : 0] src_payload;
|
reg [PAYLOAD_W - 1 : 0] src_payload;
|
wire last_cycle;
|
wire last_cycle;
|
reg packet_in_progress;
|
reg packet_in_progress;
|
reg update_grant;
|
reg update_grant;
|
|
|
wire [PAYLOAD_W - 1 : 0] sink0_payload;
|
wire [PAYLOAD_W - 1 : 0] sink0_payload;
|
wire [PAYLOAD_W - 1 : 0] sink1_payload;
|
wire [PAYLOAD_W - 1 : 0] sink1_payload;
|
|
|
assign valid[0] = sink0_valid;
|
assign valid[0] = sink0_valid;
|
assign valid[1] = sink1_valid;
|
assign valid[1] = sink1_valid;
|
|
|
wire [NUM_INPUTS - 1 : 0] eop;
|
wire [NUM_INPUTS - 1 : 0] eop;
|
assign eop[0] = sink0_endofpacket;
|
assign eop[0] = sink0_endofpacket;
|
assign eop[1] = sink1_endofpacket;
|
assign eop[1] = sink1_endofpacket;
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// Grant Logic & Updates
|
// Grant Logic & Updates
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
reg [NUM_INPUTS - 1 : 0] lock;
|
reg [NUM_INPUTS - 1 : 0] lock;
|
always @* begin
|
always @* begin
|
lock[0] = sink0_data[70];
|
lock[0] = sink0_data[70];
|
lock[1] = sink1_data[70];
|
lock[1] = sink1_data[70];
|
end
|
end
|
reg [NUM_INPUTS - 1 : 0] locked = '0;
|
reg [NUM_INPUTS - 1 : 0] locked = '0;
|
always @(posedge clk or posedge reset) begin
|
always @(posedge clk or posedge reset) begin
|
if (reset) begin
|
if (reset) begin
|
locked <= '0;
|
locked <= '0;
|
end
|
end
|
else begin
|
else begin
|
locked <= next_grant & lock;
|
locked <= next_grant & lock;
|
end
|
end
|
end
|
end
|
|
|
assign last_cycle = src_valid & src_ready & src_endofpacket & ~(|(lock & grant));
|
assign last_cycle = src_valid & src_ready & src_endofpacket & ~(|(lock & grant));
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// We're working on a packet at any time valid is high, except
|
// We're working on a packet at any time valid is high, except
|
// when this is the endofpacket.
|
// when this is the endofpacket.
|
// ------------------------------------------
|
// ------------------------------------------
|
always @(posedge clk or posedge reset) begin
|
always @(posedge clk or posedge reset) begin
|
if (reset) begin
|
if (reset) begin
|
packet_in_progress <= 1'b0;
|
packet_in_progress <= 1'b0;
|
end
|
end
|
else begin
|
else begin
|
if (last_cycle)
|
if (last_cycle)
|
packet_in_progress <= 1'b0;
|
packet_in_progress <= 1'b0;
|
else if (src_valid)
|
else if (src_valid)
|
packet_in_progress <= 1'b1;
|
packet_in_progress <= 1'b1;
|
end
|
end
|
end
|
end
|
|
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Shares
|
// Shares
|
//
|
//
|
// Special case: all-equal shares _should_ be optimized into assigning a
|
// Special case: all-equal shares _should_ be optimized into assigning a
|
// constant to next_grant_share.
|
// constant to next_grant_share.
|
// Special case: all-1's shares _should_ result in the share counter
|
// Special case: all-1's shares _should_ result in the share counter
|
// being optimized away.
|
// being optimized away.
|
// ------------------------------------------
|
// ------------------------------------------
|
// Input | arb shares | counter load value
|
// Input | arb shares | counter load value
|
// 0 | 1 | 0
|
// 0 | 1 | 0
|
// 1 | 1 | 0
|
// 1 | 1 | 0
|
wire [SHARE_COUNTER_W - 1 : 0] share_0 = 1'd0;
|
wire [SHARE_COUNTER_W - 1 : 0] share_0 = 1'd0;
|
wire [SHARE_COUNTER_W - 1 : 0] share_1 = 1'd0;
|
wire [SHARE_COUNTER_W - 1 : 0] share_1 = 1'd0;
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Choose the share value corresponding to the grant.
|
// Choose the share value corresponding to the grant.
|
// ------------------------------------------
|
// ------------------------------------------
|
reg [SHARE_COUNTER_W - 1 : 0] next_grant_share;
|
reg [SHARE_COUNTER_W - 1 : 0] next_grant_share;
|
always @* begin
|
always @* begin
|
next_grant_share =
|
next_grant_share =
|
share_0 & { SHARE_COUNTER_W {next_grant[0]} } |
|
share_0 & { SHARE_COUNTER_W {next_grant[0]} } |
|
share_1 & { SHARE_COUNTER_W {next_grant[1]} };
|
share_1 & { SHARE_COUNTER_W {next_grant[1]} };
|
end
|
end
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Flag to indicate first packet of an arb sequence.
|
// Flag to indicate first packet of an arb sequence.
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Compute the next share-count value.
|
// Compute the next share-count value.
|
// ------------------------------------------
|
// ------------------------------------------
|
reg [SHARE_COUNTER_W - 1 : 0] p1_share_count;
|
reg [SHARE_COUNTER_W - 1 : 0] p1_share_count;
|
reg [SHARE_COUNTER_W - 1 : 0] share_count;
|
reg [SHARE_COUNTER_W - 1 : 0] share_count;
|
reg share_count_zero_flag;
|
reg share_count_zero_flag;
|
|
|
always @* begin
|
always @* begin
|
// Update the counter, but don't decrement below 0.
|
// Update the counter, but don't decrement below 0.
|
p1_share_count = share_count_zero_flag ? '0 : share_count - 1'b1;
|
p1_share_count = share_count_zero_flag ? '0 : share_count - 1'b1;
|
end
|
end
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Update the share counter and share-counter=zero flag.
|
// Update the share counter and share-counter=zero flag.
|
// ------------------------------------------
|
// ------------------------------------------
|
always @(posedge clk or posedge reset) begin
|
always @(posedge clk or posedge reset) begin
|
if (reset) begin
|
if (reset) begin
|
share_count <= '0;
|
share_count <= '0;
|
share_count_zero_flag <= 1'b1;
|
share_count_zero_flag <= 1'b1;
|
end
|
end
|
else begin
|
else begin
|
if (update_grant) begin
|
if (update_grant) begin
|
share_count <= next_grant_share;
|
share_count <= next_grant_share;
|
share_count_zero_flag <= (next_grant_share == '0);
|
share_count_zero_flag <= (next_grant_share == '0);
|
end
|
end
|
else if (last_cycle) begin
|
else if (last_cycle) begin
|
share_count <= p1_share_count;
|
share_count <= p1_share_count;
|
share_count_zero_flag <= (p1_share_count == '0);
|
share_count_zero_flag <= (p1_share_count == '0);
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
always @* begin
|
always @* begin
|
update_grant = 0;
|
update_grant = 0;
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// The pipeline delays grant by one cycle, so
|
// The pipeline delays grant by one cycle, so
|
// we have to calculate the update_grant signal
|
// we have to calculate the update_grant signal
|
// one cycle ahead of time.
|
// one cycle ahead of time.
|
//
|
//
|
// Possible optimization: omit the first clause
|
// Possible optimization: omit the first clause
|
// "if (!packet_in_progress & ~src_valid) ..."
|
// "if (!packet_in_progress & ~src_valid) ..."
|
// cost: one idle cycle at the the beginning of each
|
// cost: one idle cycle at the the beginning of each
|
// grant cycle.
|
// grant cycle.
|
// benefit: save a small amount of logic.
|
// benefit: save a small amount of logic.
|
// ------------------------------------------
|
// ------------------------------------------
|
if (!packet_in_progress & !src_valid)
|
if (!packet_in_progress & !src_valid)
|
update_grant = 1;
|
update_grant = 1;
|
if (last_cycle && share_count_zero_flag)
|
if (last_cycle && share_count_zero_flag)
|
update_grant = 1;
|
update_grant = 1;
|
end
|
end
|
|
|
wire save_grant;
|
wire save_grant;
|
assign save_grant = update_grant;
|
assign save_grant = update_grant;
|
assign grant = saved_grant;
|
assign grant = saved_grant;
|
|
|
always @(posedge clk, posedge reset) begin
|
always @(posedge clk, posedge reset) begin
|
if (reset)
|
if (reset)
|
saved_grant <= '0;
|
saved_grant <= '0;
|
else if (save_grant)
|
else if (save_grant)
|
saved_grant <= next_grant;
|
saved_grant <= next_grant;
|
end
|
end
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// Arbitrator
|
// Arbitrator
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Create a request vector that stays high during
|
// Create a request vector that stays high during
|
// the packet for unpipelined arbitration.
|
// the packet for unpipelined arbitration.
|
//
|
//
|
// The pipelined arbitration scheme does not require
|
// The pipelined arbitration scheme does not require
|
// request to be held high during the packet.
|
// request to be held high during the packet.
|
// ------------------------------------------
|
// ------------------------------------------
|
reg [NUM_INPUTS - 1 : 0] prev_request;
|
reg [NUM_INPUTS - 1 : 0] prev_request;
|
always @(posedge clk, posedge reset) begin
|
always @(posedge clk, posedge reset) begin
|
if (reset)
|
if (reset)
|
prev_request <= '0;
|
prev_request <= '0;
|
else
|
else
|
prev_request <= request & ~(valid & eop);
|
prev_request <= request & ~(valid & eop);
|
end
|
end
|
|
|
assign request = (PIPELINE_ARB == 1) ? valid | locked :
|
assign request = (PIPELINE_ARB == 1) ? valid | locked :
|
prev_request | valid | locked;
|
prev_request | valid | locked;
|
|
|
wire [NUM_INPUTS - 1 : 0] next_grant_from_arb;
|
wire [NUM_INPUTS - 1 : 0] next_grant_from_arb;
|
|
|
altera_merlin_arbitrator
|
altera_merlin_arbitrator
|
#(
|
#(
|
.NUM_REQUESTERS(NUM_INPUTS),
|
.NUM_REQUESTERS(NUM_INPUTS),
|
.SCHEME ("round-robin"),
|
.SCHEME ("round-robin"),
|
.PIPELINE (1)
|
.PIPELINE (1)
|
) arb (
|
) arb (
|
.clk (clk),
|
.clk (clk),
|
.reset (reset),
|
.reset (reset),
|
.request (request),
|
.request (request),
|
.grant (next_grant_from_arb),
|
.grant (next_grant_from_arb),
|
.save_top_priority (src_valid),
|
.save_top_priority (src_valid),
|
.increment_top_priority (update_grant)
|
.increment_top_priority (update_grant)
|
);
|
);
|
|
|
assign next_grant = next_grant_from_arb;
|
assign next_grant = next_grant_from_arb;
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// Mux
|
// Mux
|
//
|
//
|
// Implemented as a sum of products.
|
// Implemented as a sum of products.
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
assign sink0_ready = src_ready && grant[0];
|
assign sink0_ready = src_ready && grant[0];
|
assign sink1_ready = src_ready && grant[1];
|
assign sink1_ready = src_ready && grant[1];
|
|
|
assign src_valid = |(grant & valid);
|
assign src_valid = |(grant & valid);
|
|
|
always @* begin
|
always @* begin
|
src_payload =
|
src_payload =
|
sink0_payload & {PAYLOAD_W {grant[0]} } |
|
sink0_payload & {PAYLOAD_W {grant[0]} } |
|
sink1_payload & {PAYLOAD_W {grant[1]} };
|
sink1_payload & {PAYLOAD_W {grant[1]} };
|
end
|
end
|
|
|
// ------------------------------------------
|
// ------------------------------------------
|
// Mux Payload Mapping
|
// Mux Payload Mapping
|
// ------------------------------------------
|
// ------------------------------------------
|
|
|
assign sink0_payload = {sink0_channel,sink0_data,
|
assign sink0_payload = {sink0_channel,sink0_data,
|
sink0_startofpacket,sink0_endofpacket};
|
sink0_startofpacket,sink0_endofpacket};
|
assign sink1_payload = {sink1_channel,sink1_data,
|
assign sink1_payload = {sink1_channel,sink1_data,
|
sink1_startofpacket,sink1_endofpacket};
|
sink1_startofpacket,sink1_endofpacket};
|
|
|
assign {src_channel,src_data,src_startofpacket,src_endofpacket} = src_payload;
|
assign {src_channel,src_data,src_startofpacket,src_endofpacket} = src_payload;
|
endmodule
|
endmodule
|
|
|
|
|
|
|