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