1
0
mirror of https://github.com/KastnerRG/riffa.git synced 2025-01-30 23:02:54 +08:00
riffa/fpga/riffa_hdl/tx_engine_classic.v
2016-02-09 15:23:37 -08:00

904 lines
39 KiB
Verilog

// ----------------------------------------------------------------------
// Copyright (c) 2016, The Regents of the University of California All
// rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of The Regents of the University of California
// nor the names of its contributors may be used to endorse or
// promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
// UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
// ----------------------------------------------------------------------
//
// Filename: tx_engine_classic.v
// Version: 1.0
// Verilog Standard: Verilog-2001
// Description: The TX Engine takes unformatted request and completions,
// formats these packets into "TLP's" or Transaction Layer Packets and abitrates
// their sending over the PCIe bus. These packets must meet max-request,
// max-payload, and payload termination requirements (see Read Completion
// Boundary). The TX Engine does not check these requirements during operation,
// but may do so during simulation.
//
// Valid packets are transmitted over the shared PCIe bus as determined
// by the arbiter.
//
// This Engine is capable of operating at "line rate".
// Author: Dustin Richmond (@darichmond)
//-----------------------------------------------------------------------------
`include "trellis.vh"
`include "tlp.vh"
module tx_engine_classic
#(parameter C_PCI_DATA_WIDTH = 128,
parameter C_PIPELINE_INPUT = 1,
parameter C_PIPELINE_OUTPUT = 1,
parameter C_MAX_PAYLOAD_DWORDS = 256,
parameter C_VENDOR = "ALTERA")
(// Interface: Clocks
input CLK,
// Interface: Resets
input RST_BUS, // Replacement for generic RST_IN
input RST_LOGIC, // Addition for RIFFA_RST
output DONE_TXC_RST,
output DONE_TXR_RST,
// Interface: Configuration
input [`SIG_CPLID_W-1:0] CONFIG_COMPLETER_ID,
// Interface: TX Classic
input TX_TLP_READY,
output [C_PCI_DATA_WIDTH-1:0] TX_TLP,
output TX_TLP_VALID,
output TX_TLP_START_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_START_OFFSET,
output TX_TLP_END_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_END_OFFSET,
// Interface: TXC Engine
input TXC_DATA_VALID,
input [C_PCI_DATA_WIDTH-1:0] TXC_DATA,
input TXC_DATA_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_DATA_START_OFFSET,
input TXC_DATA_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_DATA_END_OFFSET,
output TXC_DATA_READY,
input TXC_META_VALID,
input [`SIG_FBE_W-1:0] TXC_META_FDWBE,
input [`SIG_LBE_W-1:0] TXC_META_LDWBE,
input [`SIG_LOWADDR_W-1:0] TXC_META_ADDR,
input [`SIG_TYPE_W-1:0] TXC_META_TYPE,
input [`SIG_LEN_W-1:0] TXC_META_LENGTH,
input [`SIG_BYTECNT_W-1:0] TXC_META_BYTE_COUNT,
input [`SIG_TAG_W-1:0] TXC_META_TAG,
input [`SIG_REQID_W-1:0] TXC_META_REQUESTER_ID,
input [`SIG_TC_W-1:0] TXC_META_TC,
input [`SIG_ATTR_W-1:0] TXC_META_ATTR,
input TXC_META_EP,
output TXC_META_READY,
output TXC_SENT,
// Interface: TXR Engine
input TXR_DATA_VALID,
input [C_PCI_DATA_WIDTH-1:0] TXR_DATA,
input TXR_DATA_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_DATA_START_OFFSET,
input TXR_DATA_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_DATA_END_OFFSET,
output TXR_DATA_READY,
input TXR_META_VALID,
input [`SIG_FBE_W-1:0] TXR_META_FDWBE,
input [`SIG_LBE_W-1:0] TXR_META_LDWBE,
input [`SIG_ADDR_W-1:0] TXR_META_ADDR,
input [`SIG_LEN_W-1:0] TXR_META_LENGTH,
input [`SIG_TAG_W-1:0] TXR_META_TAG,
input [`SIG_TC_W-1:0] TXR_META_TC,
input [`SIG_ATTR_W-1:0] TXR_META_ATTR,
input [`SIG_TYPE_W-1:0] TXR_META_TYPE,
input TXR_META_EP,
output TXR_META_READY,
output TXR_SENT);
localparam C_MUX_TYPE = "SHIFT";
localparam C_DEPTH_PACKETS = 10;
localparam C_RST_COUNT = 10;
/*AUTOWIRE*/
/*AUTOINPUT*/
wire [C_PCI_DATA_WIDTH-1:0] _TXC_DATA;
wire [C_PCI_DATA_WIDTH-1:0] _TXR_DATA;
wire [C_PCI_DATA_WIDTH-1:0] wTxcTlp;
wire wTxcTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxcTlpEndOffset;
wire wTxcTlpReady;
wire wTxcTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxcTlpStartOffset;
wire wTxcTlpValid;
wire [C_PCI_DATA_WIDTH-1:0] wTxrTlp;
wire wTxrTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxrTlpEndOffset;
wire wTxrTlpReady;
wire wTxrTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxrTlpStartOffset;
wire wTxrTlpValid;
wire [C_PCI_DATA_WIDTH-1:0] wTxTlp;
wire wTxTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxTlpEndOffset;
wire wTxTlpReady;
wire wTxTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxTlpStartOffset;
wire wTxTlpValid;
wire wDoneTxcEngRst;
wire wDoneTxrEngRst;
wire wDoneRst;
wire wRstWaiting;
wire wRstRc;
wire wRstEng;
wire [C_RST_COUNT:0] wShiftRst;
reg rTxValid;
reg [`TLP_TYPE_W-1:0] rTxType;
reg rTxEndFlag;
reg rTxrSent;
reg rTxcSent;
assign DONE_TXC_RST = wDoneRst & wDoneTxcEngRst;
assign DONE_TXR_RST = wDoneRst & wDoneTxrEngRst;
assign TXC_SENT = rTxcSent;
assign TXR_SENT = rTxrSent;
assign wRstEng = wShiftRst[C_RST_COUNT-3];
assign wDoneEngRst = ~wShiftRst[C_RST_COUNT];
always @(posedge CLK) begin
if(TX_TLP_START_FLAG) begin
rTxType <= TX_TLP[`TLP_TYPE_R];
end
rTxEndFlag <= TX_TLP_END_FLAG;
rTxValid <= TX_TLP_VALID & TX_TLP_READY;
rTxcSent <= rTxEndFlag & rTxValid & (rTxType == `TLP_TYPE_CPL);
rTxrSent <= rTxEndFlag & rTxValid & (rTxType == `TLP_TYPE_REQ);
end
generate
if(C_VENDOR == "XILINX") begin : xilinx_data
if(C_PCI_DATA_WIDTH == 128) begin : x_be_swap128
assign _TXC_DATA = {TXC_DATA[103:96], TXC_DATA[111:104], TXC_DATA[119:112], TXC_DATA[127:120],
TXC_DATA[71:64], TXC_DATA[79:72], TXC_DATA[87:80], TXC_DATA[95:88],
TXC_DATA[39:32], TXC_DATA[47:40], TXC_DATA[55:48], TXC_DATA[63:56],
TXC_DATA[07:00], TXC_DATA[15:08], TXC_DATA[23:16], TXC_DATA[31:24]};
assign _TXR_DATA = {TXR_DATA[103:96], TXR_DATA[111:104], TXR_DATA[119:112], TXR_DATA[127:120],
TXR_DATA[71:64], TXR_DATA[79:72], TXR_DATA[87:80], TXR_DATA[95:88],
TXR_DATA[39:32], TXR_DATA[47:40], TXR_DATA[55:48], TXR_DATA[63:56],
TXR_DATA[07:00], TXR_DATA[15:08], TXR_DATA[23:16], TXR_DATA[31:24]};
end else if(C_PCI_DATA_WIDTH == 64) begin: x_be_swap64
assign _TXC_DATA = {TXC_DATA[39:32], TXC_DATA[47:40], TXC_DATA[55:48], TXC_DATA[63:56],
TXC_DATA[07:00], TXC_DATA[15:08], TXC_DATA[23:16], TXC_DATA[31:24]};
assign _TXR_DATA = {TXR_DATA[39:32], TXR_DATA[47:40], TXR_DATA[55:48], TXR_DATA[63:56],
TXR_DATA[07:00], TXR_DATA[15:08], TXR_DATA[23:16], TXR_DATA[31:24]};
end else if(C_PCI_DATA_WIDTH == 32) begin: x_be_swap32
assign _TXC_DATA = {TXC_DATA[07:00], TXC_DATA[15:08], TXC_DATA[23:16], TXC_DATA[31:24]};
assign _TXR_DATA = {TXR_DATA[07:00], TXR_DATA[15:08], TXR_DATA[23:16], TXR_DATA[31:24]};
end
end else begin : altera_data
assign _TXC_DATA = TXC_DATA;
assign _TXR_DATA = TXR_DATA;
end
endgenerate
txc_engine_classic
#(.C_PIPELINE_OUTPUT (0),
/*AUTOINSTPARAM*/
// Parameters
.C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH),
.C_PIPELINE_INPUT (C_PIPELINE_INPUT),
.C_MAX_PAYLOAD_DWORDS (C_MAX_PAYLOAD_DWORDS),
.C_DEPTH_PACKETS (C_DEPTH_PACKETS),
.C_VENDOR (C_VENDOR))
txc_engine_inst
(// Outputs
.TXC_TLP (wTxcTlp[C_PCI_DATA_WIDTH-1:0] ),
.TXC_TLP_VALID (wTxcTlpValid),
.TXC_TLP_START_FLAG (wTxcTlpStartFlag),
.TXC_TLP_START_OFFSET (wTxcTlpStartOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXC_TLP_END_FLAG (wTxcTlpEndFlag),
.TXC_TLP_END_OFFSET (wTxcTlpEndOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.DONE_TXC_RST (wDoneTxcEngRst),
// Inputs
.TXC_TLP_READY (wTxcTlpReady),
.TXC_DATA (_TXC_DATA[C_PCI_DATA_WIDTH-1:0]),
.RST_IN (wRstEng),
/*AUTOINST*/
// Outputs
.TXC_DATA_READY (TXC_DATA_READY),
.TXC_META_READY (TXC_META_READY),
// Inputs
.CLK (CLK),
.CONFIG_COMPLETER_ID (CONFIG_COMPLETER_ID[`SIG_CPLID_W-1:0]),
.TXC_DATA_VALID (TXC_DATA_VALID),
.TXC_DATA_START_FLAG (TXC_DATA_START_FLAG),
.TXC_DATA_START_OFFSET (TXC_DATA_START_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXC_DATA_END_FLAG (TXC_DATA_END_FLAG),
.TXC_DATA_END_OFFSET (TXC_DATA_END_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXC_META_VALID (TXC_META_VALID),
.TXC_META_FDWBE (TXC_META_FDWBE[`SIG_FBE_W-1:0]),
.TXC_META_LDWBE (TXC_META_LDWBE[`SIG_LBE_W-1:0]),
.TXC_META_ADDR (TXC_META_ADDR[`SIG_LOWADDR_W-1:0]),
.TXC_META_TYPE (TXC_META_TYPE[`SIG_TYPE_W-1:0]),
.TXC_META_LENGTH (TXC_META_LENGTH[`SIG_LEN_W-1:0]),
.TXC_META_BYTE_COUNT (TXC_META_BYTE_COUNT[`SIG_BYTECNT_W-1:0]),
.TXC_META_TAG (TXC_META_TAG[`SIG_TAG_W-1:0]),
.TXC_META_REQUESTER_ID (TXC_META_REQUESTER_ID[`SIG_REQID_W-1:0]),
.TXC_META_TC (TXC_META_TC[`SIG_TC_W-1:0]),
.TXC_META_ATTR (TXC_META_ATTR[`SIG_ATTR_W-1:0]),
.TXC_META_EP (TXC_META_EP));
txr_engine_classic
#(.C_PIPELINE_OUTPUT (0),
/*AUTOINSTPARAM*/
// Parameters
.C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH),
.C_PIPELINE_INPUT (C_PIPELINE_INPUT),
.C_MAX_PAYLOAD_DWORDS (C_MAX_PAYLOAD_DWORDS),
.C_DEPTH_PACKETS (C_DEPTH_PACKETS),
.C_VENDOR (C_VENDOR))
txr_engine_inst
(// Outputs
.TXR_TLP (wTxrTlp[C_PCI_DATA_WIDTH-1:0]),
.TXR_TLP_VALID (wTxrTlpValid),
.TXR_TLP_START_FLAG (wTxrTlpStartFlag),
.TXR_TLP_START_OFFSET (wTxrTlpStartOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_TLP_END_FLAG (wTxrTlpEndFlag),
.TXR_TLP_END_OFFSET (wTxrTlpEndOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_DATA (_TXR_DATA[C_PCI_DATA_WIDTH-1:0]),
.DONE_TXR_RST (wDoneTxrEngRst),
// Inputs
.TXR_TLP_READY (wTxrTlpReady),
.RST_IN (wRstEng),
/*AUTOINST*/
// Outputs
.TXR_DATA_READY (TXR_DATA_READY),
.TXR_META_READY (TXR_META_READY),
// Inputs
.CLK (CLK),
.CONFIG_COMPLETER_ID (CONFIG_COMPLETER_ID[`SIG_CPLID_W-1:0]),
.TXR_DATA_VALID (TXR_DATA_VALID),
.TXR_DATA_START_FLAG (TXR_DATA_START_FLAG),
.TXR_DATA_START_OFFSET (TXR_DATA_START_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_DATA_END_FLAG (TXR_DATA_END_FLAG),
.TXR_DATA_END_OFFSET (TXR_DATA_END_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_META_VALID (TXR_META_VALID),
.TXR_META_FDWBE (TXR_META_FDWBE[`SIG_FBE_W-1:0]),
.TXR_META_LDWBE (TXR_META_LDWBE[`SIG_LBE_W-1:0]),
.TXR_META_ADDR (TXR_META_ADDR[`SIG_ADDR_W-1:0]),
.TXR_META_LENGTH (TXR_META_LENGTH[`SIG_LEN_W-1:0]),
.TXR_META_TAG (TXR_META_TAG[`SIG_TAG_W-1:0]),
.TXR_META_TC (TXR_META_TC[`SIG_TC_W-1:0]),
.TXR_META_ATTR (TXR_META_ATTR[`SIG_ATTR_W-1:0]),
.TXR_META_TYPE (TXR_META_TYPE[`SIG_TYPE_W-1:0]),
.TXR_META_EP (TXR_META_EP));
tx_mux
#(.C_PIPELINE_INPUT (0),
/*AUTOINSTPARAM*/
// Parameters
.C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH),
.C_PIPELINE_OUTPUT (C_PIPELINE_OUTPUT),
.C_MUX_TYPE (C_MUX_TYPE),
.C_VENDOR (C_VENDOR))
tx_mux_inst
(// Inputs
.TXC_TLP (wTxcTlp[C_PCI_DATA_WIDTH-1:0]),
.TXC_TLP_VALID (wTxcTlpValid),
.TXC_TLP_START_FLAG (wTxcTlpStartFlag),
.TXC_TLP_START_OFFSET (wTxcTlpStartOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXC_TLP_END_FLAG (wTxcTlpEndFlag),
.TXC_TLP_END_OFFSET (wTxcTlpEndOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_TLP (wTxrTlp[C_PCI_DATA_WIDTH-1:0]),
.TXR_TLP_VALID (wTxrTlpValid),
.TXR_TLP_START_FLAG (wTxrTlpStartFlag),
.TXR_TLP_START_OFFSET (wTxrTlpStartOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TXR_TLP_END_FLAG (wTxrTlpEndFlag),
.TXR_TLP_END_OFFSET (wTxrTlpEndOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.RST_IN (wRstEng),
// Outputs
.TXC_TLP_READY (wTxcTlpReady),
.TXR_TLP_READY (wTxrTlpReady),
.TX_TLP (wTxTlp[C_PCI_DATA_WIDTH-1:0]),
.TX_TLP_VALID (wTxTlpValid),
.TX_TLP_START_FLAG (wTxTlpStartFlag),
.TX_TLP_START_OFFSET (wTxTlpStartOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TX_TLP_END_FLAG (wTxTlpEndFlag),
.TX_TLP_END_OFFSET (wTxTlpEndOffset[clog2s(C_PCI_DATA_WIDTH/32)-1:0]),
.TX_TLP_READY (wTxTlpReady),
/*AUTOINST*/
// Inputs
.CLK (CLK));
shiftreg
#(// Parameters
.C_DEPTH (C_RST_COUNT),
.C_WIDTH (1),
.C_VALUE (1)
/*AUTOINSTPARAM*/)
rst_shiftreg
(// Outputs
.RD_DATA (wShiftRst),
// Inputs
.RST_IN (RST_BUS),
.WR_DATA (wRstRc),
/*AUTOINST*/
// Inputs
.CLK (CLK));
reset_controller
#(// Parameters
.C_RST_COUNT (C_RST_COUNT)
/*AUTOINSTPARAM*/)
rc_inst
(// Outputs
.DONE_RST (wDoneRst),
.WAITING_RESET (wRstWaiting),
.RST_OUT (wRstRc),
// Inputs
.RST_IN (RST_BUS),
.SIGNAL_RST (RST_LOGIC),
.WAIT_RST (TX_TLP_VALID),
.NEXT_CYC_RST (TX_TLP_END_FLAG & TX_TLP_READY),
/*AUTOINST*/
// Inputs
.CLK (CLK));
pipeline
#(// Parameters
.C_DEPTH (1),
.C_WIDTH (C_PCI_DATA_WIDTH +
2*(1 + clog2s(C_PCI_DATA_WIDTH/32))),
.C_USE_MEMORY (0)
/*AUTOINSTPARAM*/)
output_reg_inst
(// Outputs
.WR_DATA_READY (wTxTlpReady),
.RD_DATA ({TX_TLP,
TX_TLP_START_FLAG, TX_TLP_START_OFFSET,
TX_TLP_END_FLAG, TX_TLP_END_OFFSET}),
.RD_DATA_VALID (TX_TLP_VALID),
// Inputs
.RST_IN (wRstRc),
.WR_DATA ({wTxTlp,
wTxTlpStartFlag, wTxTlpStartOffset,
wTxTlpEndFlag, wTxTlpEndOffset}),
.WR_DATA_VALID (wTxTlpValid & ~wRstWaiting),
.RD_DATA_READY (TX_TLP_READY),
/*AUTOINST*/
// Inputs
.CLK (CLK));
// Put output pipeline stage here, OR, at TX Engine outputs
endmodule
// Local Variables:
// verilog-library-directories:("." "../../common/")
// End:
/*
Filename: tx_mux.v
Version: 1.0
Verilog Standard: Verilog-2001
Description: The tx_mux arbitrates access to the PCI TX interface
between the the Request and Completion engines. The top level tx_mux
module instantiates two sub-modules (also declared in this file):
tx_arbiter and tx_phi. The arbiter choses the next packet that will
be granted the TX interface, based on the priorities given to
it. Each priority is the count of how many successive, back-to-back
packets can be sent by either the TXC or TXR interface before
granting time to the other engine. The mux is a simple multiplexer
that uses the select signals from the arbiter.
Notes: Any modifications to this file should meet the conditions set
forth in the "Trellis Style Guide"
- The pipeline stage at the start of the mux means that ready stays high for
both TXC and TXR. This the behavior we want?
Author: Dustin Richmond (@darichmond)
Co-Authors:
*/
`timescale 1ns/1ns
`include "trellis.vh"
module tx_mux
#(parameter C_PCI_DATA_WIDTH = 128,
parameter C_PIPELINE_INPUT = 1,
parameter C_PIPELINE_OUTPUT = 1,
parameter C_MUX_TYPE = "SHIFT",
parameter C_VENDOR = "ALTERA")
(// Interface: Clocks
input CLK,
// Interface: Resets
input RST_IN,
// Interface: TXC
input [C_PCI_DATA_WIDTH-1:0] TXC_TLP,
output TXC_TLP_READY,
input TXC_TLP_VALID,
input TXC_TLP_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_TLP_START_OFFSET,
input TXC_TLP_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_TLP_END_OFFSET,
// Interface: TXR
input [C_PCI_DATA_WIDTH-1:0] TXR_TLP,
input TXR_TLP_VALID,
input TXR_TLP_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_TLP_START_OFFSET,
input TXR_TLP_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_TLP_END_OFFSET,
output TXR_TLP_READY,
// Interface: TX Classic
input TX_TLP_READY,
output [C_PCI_DATA_WIDTH-1:0] TX_TLP,
output TX_TLP_VALID,
output TX_TLP_START_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_START_OFFSET,
output TX_TLP_END_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_END_OFFSET);
localparam C_WIDTH = (C_PCI_DATA_WIDTH + 2 * (clog2s(C_PCI_DATA_WIDTH/32) + 1));
localparam C_TXC_PRIORITY = 1;
localparam C_TXR_PRIORITY = 2;
/*AUTOWIRE*/
/*AUTOINPUT*/
/*AUTOOUTPUT*/
// Input Pipeline Stage to Mux
wire [C_PCI_DATA_WIDTH-1:0] wTxcTlp;
wire wTxcTlpReady;
wire wTxcTlpValid;
wire wTxcTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxcTlpStartOffset;
wire wTxcTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxcTlpEndOffset;
wire [C_PCI_DATA_WIDTH-1:0] wTxrTlp;
wire wTxrTlpReady;
wire wTxrTlpValid;
wire wTxrTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxrTlpStartOffset;
wire wTxrTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxrTlpEndOffset;
// Output of Mux to
wire [C_PCI_DATA_WIDTH-1:0] wTxTlp;
wire wTxTlpReady;
wire wTxTlpValid;
wire wTxTlpStartFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxTlpStartOffset;
wire wTxTlpEndFlag;
wire [clog2s(C_PCI_DATA_WIDTH/32)-1:0] wTxTlpEndOffset;
pipeline
#(// Parameters
.C_DEPTH (C_PIPELINE_INPUT?1:0),
.C_USE_MEMORY (0),
/*AUTOINSTPARAM*/
// Parameters
.C_WIDTH (C_WIDTH))
txr_capture_inst
(// Outputs
.WR_DATA_READY (TXR_TLP_READY),
.RD_DATA ({wTxrTlp, wTxrTlpStartFlag, wTxrTlpStartOffset,
wTxrTlpEndFlag, wTxrTlpEndOffset}),
.RD_DATA_VALID (wTxrTlpValid),
// Inputs
.WR_DATA ({TXR_TLP,
TXR_TLP_START_FLAG, TXR_TLP_START_OFFSET,
TXR_TLP_END_FLAG, TXR_TLP_END_OFFSET}),
.WR_DATA_VALID (TXR_TLP_VALID),
.RD_DATA_READY (wTxrTlpReady),
/*AUTOINST*/
// Inputs
.CLK (CLK),
.RST_IN (RST_IN));
pipeline
#(// Parameters
.C_DEPTH (C_PIPELINE_INPUT?1:0),
.C_USE_MEMORY (0),
/*AUTOINSTPARAM*/
// Parameters
.C_WIDTH (C_WIDTH))
txc_capture_inst
(// Outputs
.WR_DATA_READY (TXC_TLP_READY),
.RD_DATA ({wTxcTlp, wTxcTlpStartFlag, wTxcTlpStartOffset,
wTxcTlpEndFlag, wTxcTlpEndOffset}),
.RD_DATA_VALID (wTxcTlpValid),
// Inputs
.WR_DATA ({TXC_TLP,
TXC_TLP_START_FLAG, TXC_TLP_START_OFFSET,
TXC_TLP_END_FLAG, TXC_TLP_END_OFFSET}),
.WR_DATA_VALID (TXC_TLP_VALID),
.RD_DATA_READY (wTxcTlpReady),
/*AUTOINST*/
// Inputs
.CLK (CLK),
.RST_IN (RST_IN));
tx_arbiter
#(/*AUTOINSTPARAM*/
// Parameters
.C_TXC_PRIORITY (C_TXC_PRIORITY),
.C_TXR_PRIORITY (C_TXR_PRIORITY))
tx_arbiter_inst
(// Outputs
.TXR_TLP_READY (wTxrTlpReady),
.TXC_TLP_READY (wTxcTlpReady),
// Inputs
.TX_TLP_READY (wTxTlpReady),
.TXC_TLP_VALID (wTxcTlpValid),
.TXC_TLP_START_FLAG (wTxcTlpStartFlag),
.TXC_TLP_END_FLAG (wTxcTlpEndFlag),
.TXR_TLP_VALID (wTxrTlpValid),
.TXR_TLP_START_FLAG (wTxrTlpStartFlag),
.TXR_TLP_END_FLAG (wTxrTlpEndFlag),
/*AUTOINST*/
// Inputs
.CLK (CLK),
.RST_IN (RST_IN));
// MUX Selector
tx_phi
#(/*AUTOINSTPARAM*/
// Parameters
.C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH),
.C_MUX_TYPE (C_MUX_TYPE),
.C_WIDTH (C_WIDTH))
tx_phi_inst
(// Outputs
.TXC_TLP_READY (wTxcTlpReady),
.TXR_TLP_READY (wTxrTlpReady),
.TX_TLP (wTxTlp),
.TX_TLP_VALID (wTxTlpValid),
.TX_TLP_START_FLAG (wTxTlpStartFlag),
.TX_TLP_START_OFFSET (wTxTlpStartOffset),
.TX_TLP_END_FLAG (wTxTlpEndFlag),
.TX_TLP_END_OFFSET (wTxTlpEndOffset),
// Inputs
.TXC_TLP (wTxcTlp),
.TXC_TLP_VALID (wTxcTlpValid),
.TXC_TLP_START_FLAG (wTxcTlpStartFlag),
.TXC_TLP_START_OFFSET (wTxcTlpStartOffset),
.TXC_TLP_END_FLAG (wTxcTlpEndFlag),
.TXC_TLP_END_OFFSET (wTxcTlpEndOffset),
.TXR_TLP (wTxrTlp),
.TXR_TLP_VALID (wTxrTlpValid),
.TXR_TLP_START_FLAG (wTxrTlpStartFlag),
.TXR_TLP_START_OFFSET (wTxrTlpStartOffset),
.TXR_TLP_END_FLAG (wTxrTlpEndFlag),
.TXR_TLP_END_OFFSET (wTxrTlpEndOffset),
/*AUTOINST*/
// Inputs
.CLK (CLK),
.RST_IN (RST_IN));
pipeline
#(// Parameters
.C_DEPTH (C_PIPELINE_OUTPUT?1:0),
.C_USE_MEMORY (0),
/*AUTOINSTPARAM*/
// Parameters
.C_WIDTH (C_WIDTH))
tx_output_inst
(// Outputs
.WR_DATA_READY (wTxTlpReady),
.RD_DATA ({TX_TLP,
TX_TLP_START_FLAG, TX_TLP_START_OFFSET,
TX_TLP_END_FLAG, TX_TLP_END_OFFSET}),
.RD_DATA_VALID (TX_TLP_VALID),
// Inputs
.WR_DATA ({wTxTlp, wTxTlpStartFlag, wTxTlpStartOffset,
wTxTlpEndFlag, wTxTlpEndOffset}),
.WR_DATA_VALID (wTxTlpValid),
.RD_DATA_READY (TX_TLP_READY),
/*AUTOINST*/
// Inputs
.CLK (CLK),
.RST_IN (RST_IN));
endmodule
// Local Variables:
// verilog-library-directories:("." "../../../common/")
// End:
/*
Description: The tx_arbiter arbitrates between TXC and TXR channels. The C_TX*_PRIORITY
values are counters are the maximum number of uninterrupted TXR or TXC packets that can be
transmitted without transmitting a packet of the other type.
Notes: Any modifications to this file should meet the conditions set
forth in the "Trellis Style Guide"
Author: Dustin Richmond (@darichmond)
Co-Authors:
*/
module tx_arbiter
#(parameter C_TXC_PRIORITY = 1,
parameter C_TXR_PRIORITY = 1)
(
// Interface: Clocks
input CLK,
// Interface: Resets
input RST_IN,
// Interface: TX Classic Flow Control
input TX_TLP_READY,
// Interface: TXR Flow Control
output TXR_TLP_READY,
input TXR_TLP_VALID,
input TXR_TLP_START_FLAG,
input TXR_TLP_END_FLAG,
// Interface: TXC Flow Control
output TXC_TLP_READY,
input TXC_TLP_VALID,
input TXC_TLP_START_FLAG,
input TXC_TLP_END_FLAG);
localparam S_TXARB_IDLE = 0; // STATE: Idle state for the arbiter (not currently used)
localparam S_TXARB_TRANSMIT_TXR = 1; // STATE: Transmit TXR packets until the priority counter is reached
localparam S_TXARB_TRANSMIT_TXC = 2; // STATE: Transmit TXC packets until the priority counter is reached
// S_TXARB_PRIORITY is a special state that encodes the type (TXR/TXC) with
// higher priority so that the state machine (below) is general.
localparam S_TXARB_PRIORITY = (S_TXARB_TRANSMIT_TXR >= S_TXARB_TRANSMIT_TXC)? S_TXARB_TRANSMIT_TXR: S_TXARB_TRANSMIT_TXC;
localparam C_NUM_STATES = S_TXARB_TRANSMIT_TXC;
wire wTxrGrant;
wire wTxrReq;
wire wTxrDone;
wire wTxcGrant;
wire wTxcReq;
wire wTxcDone;
reg [clog2s(C_NUM_STATES):0] rArbState,_rArbState;
reg rTxrLast,_rTxrLast; // Reset on RST_IN or TXC_TLP_READY
reg rTxcLast,_rTxcLast; // Reset on RST_IN or TXR_TLP_READY
reg rTxrActive,_rTxrActive; // Reset on RST_IN or TXC_TLP_READY
reg rTxcActive,_rTxcActive; // Reset on RST_IN or TXR_TLP_READY
reg [clog2s(C_TXC_PRIORITY)-1:0] rTxcCounter,_rTxcCounter; // Reset on RST_IN or TXC_TLP_READY
reg [clog2s(C_TXR_PRIORITY)-1:0] rTxrCounter,_rTxrCounter; // Reset on RST_IN or TXR_TLP_READY
assign TXR_TLP_READY = wTxrGrant & TX_TLP_READY; // TODO: Not great
assign wTxrReq = TXR_TLP_START_FLAG & TXR_TLP_VALID;
assign wTxrDone = TXR_TLP_END_FLAG & TXR_TLP_READY;
assign wTxrGrant = (rArbState == S_TXARB_TRANSMIT_TXR);
assign TXC_TLP_READY = wTxcGrant & TX_TLP_READY; // TODO: Not great
assign wTxcReq = TXC_TLP_START_FLAG & TXC_TLP_VALID;
assign wTxcDone = TXC_TLP_END_FLAG & TXC_TLP_READY;
assign wTxcGrant = (rArbState == S_TXARB_TRANSMIT_TXC);
always @(*) begin
// Defaults
_rTxcCounter = rTxcCounter;
_rTxcActive = rTxcActive;
_rTxcLast = rTxcLast;
if(wTxrGrant) begin
_rTxcCounter = 0;
end else if(wTxcReq & wTxcGrant & ~rTxcLast) begin
_rTxcCounter = _rTxcCounter + 1;
end
if(wTxcReq & wTxcGrant) begin
_rTxcActive = 1;
end else if(wTxcDone) begin
_rTxcActive = 0;
end
if(wTxrGrant | RST_IN) begin
_rTxcLast = 0;
end else if(wTxcReq & wTxcGrant) begin
_rTxcLast = (rTxcCounter == (C_TXC_PRIORITY - 1));
end
end // always @ (*)
always @(posedge CLK) begin
if(RST_IN) begin
rTxcCounter <= #1 0;
rTxcActive <= #1 0;
rTxcLast <= #1 0;
end else begin
rTxcCounter <= #1 _rTxcCounter;
rTxcActive <= #1 _rTxcActive;
rTxcLast <= #1 _rTxcLast;
end
end
always @(*) begin
// Defaults
_rTxrCounter = rTxrCounter;
_rTxrActive = rTxrActive;
_rTxrLast = rTxrLast;
if(wTxcGrant) begin
_rTxrCounter = 0;
end else if(wTxrReq & wTxrGrant & ~rTxrLast) begin
_rTxrCounter = _rTxrCounter + 1;
end
if(wTxrReq & wTxrGrant) begin
_rTxrActive = 1;
end else if(wTxrDone) begin
_rTxrActive = 0;
end
if(wTxcGrant | RST_IN) begin
_rTxrLast = 0;
end else if(wTxrReq & wTxrGrant) begin
/* verilator lint_off WIDTH */
_rTxrLast = (rTxrCounter == (C_TXR_PRIORITY - 1));
/* verilator lint_on WIDTH */
end
end
always @(posedge CLK) begin
if(RST_IN) begin
rTxrCounter <= #1 0;
rTxrActive <= #1 0;
rTxrLast <= #1 0;
end else begin
rTxrCounter <= #1 _rTxrCounter;
rTxrActive <= #1 _rTxrActive;
rTxrLast <= #1 _rTxrLast;
end
end
// User encoded state machine
always @(*) begin
_rArbState = rArbState;
case(rArbState)
S_TXARB_TRANSMIT_TXR: begin
if((rTxrLast & wTxrDone & wTxcReq) | (~rTxrActive & ~wTxrReq & wTxcReq)) begin
_rArbState = S_TXARB_TRANSMIT_TXC;
end
end
S_TXARB_TRANSMIT_TXC: begin
if((rTxcLast & wTxcDone & wTxrReq) | (~rTxcActive & ~wTxcReq & wTxrReq)) begin
_rArbState = S_TXARB_TRANSMIT_TXR;
end
end
default: begin
// Error! This should never happen...
end
endcase
end // always @ begin
always @(posedge CLK) begin
if(RST_IN) begin
rArbState <= #1 S_TXARB_PRIORITY;
end else begin
rArbState <= #1 _rArbState;
end
end
endmodule
/*
Description: The tx_phi wraps a mux instantiation for the tx_mux. It is
controlled by the tx_arbiter
Notes: Any modifications to this file should meet the conditions set
forth in the "Trellis Style Guide"
Author: Dustin Richmond (@darichmond)
Co-Authors:
*/
module tx_phi
#(parameter C_PCI_DATA_WIDTH = 10'd128,
parameter C_MUX_TYPE = "SHIFT",
parameter C_WIDTH = (C_PCI_DATA_WIDTH + 2 * (clog2s(C_PCI_DATA_WIDTH/32) + 1)))
(// Interface: Clocks
input CLK,
// Interface: Resets
input RST_IN,
// Interface: TXC Flow Control
input TXC_TLP_READY,
// Interface: TXR Flow Control
input TXR_TLP_READY,
// Interface: TXC
input [C_PCI_DATA_WIDTH-1:0] TXC_TLP,
input TXC_TLP_VALID,
input TXC_TLP_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_TLP_START_OFFSET,
input TXC_TLP_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXC_TLP_END_OFFSET,
// Interface: TXR
input [C_PCI_DATA_WIDTH-1:0] TXR_TLP,
input TXR_TLP_VALID,
input TXR_TLP_START_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_TLP_START_OFFSET,
input TXR_TLP_END_FLAG,
input [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_TLP_END_OFFSET,
// Interface: TX Classic
output [C_PCI_DATA_WIDTH-1:0] TX_TLP,
output TX_TLP_VALID,
output TX_TLP_START_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_START_OFFSET,
output TX_TLP_END_FLAG,
output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TX_TLP_END_OFFSET);
// Width = 2 * (DATA WIDTH + VALID + START FLAG + START OFFSET + END FLAG + END OFFSET)
localparam C_MUX_WIDTH = C_PCI_DATA_WIDTH + 3 + 2*clog2s(C_PCI_DATA_WIDTH/32);
wire [2*C_MUX_WIDTH-1:0] wAggregate;
assign wAggregate = {{TXR_TLP,TXR_TLP_VALID,TXR_TLP_START_FLAG,
TXR_TLP_START_OFFSET,TXR_TLP_END_FLAG,TXR_TLP_END_OFFSET},
{TXC_TLP,TXC_TLP_VALID,TXC_TLP_START_FLAG,
TXC_TLP_START_OFFSET,TXC_TLP_END_FLAG,TXC_TLP_END_OFFSET}};
mux
#(// Parameters
.C_NUM_INPUTS (2),
.C_CLOG_NUM_INPUTS (1),
.C_WIDTH (C_MUX_WIDTH),
.C_MUX_TYPE ("SELECT")
/*AUTOINSTPARAM*/)
mux_inst
(// Outputs
.MUX_OUTPUT ({TX_TLP,TX_TLP_VALID,TX_TLP_START_FLAG,
TX_TLP_START_OFFSET,TX_TLP_END_FLAG,
TX_TLP_END_OFFSET}),
// Inputs
.MUX_INPUTS (wAggregate),
.MUX_SELECT (TXR_TLP_READY)
/*AUTOINST*/);
endmodule