mirror of
https://github.com/KastnerRG/riffa.git
synced 2025-01-30 23:02:54 +08:00
231 lines
9.1 KiB
Verilog
231 lines
9.1 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: translation_layer.v
|
|
Version: 1.0
|
|
Verilog Standard: Verilog-2001
|
|
|
|
Description: The translation layer provides a uniform interface for all Altera
|
|
PCIe interfaces
|
|
|
|
Notes: Any modifications to this file should meet the conditions set
|
|
forth in the "Trellis Style Guide"
|
|
|
|
Author: Dustin Richmond (@darichmond)
|
|
Co-Authors:
|
|
*/
|
|
`include "trellis.vh" // Defines the user-facing signal widths.
|
|
`include "altera.vh"
|
|
module translation_altera
|
|
#(
|
|
parameter C_PCI_DATA_WIDTH = 128
|
|
)
|
|
(
|
|
input CLK,
|
|
input RST_IN,
|
|
|
|
// Interface: Altera RX
|
|
input [C_PCI_DATA_WIDTH-1:0] RX_ST_DATA,
|
|
input [0:0] RX_ST_EOP,
|
|
input [0:0] RX_ST_SOP,
|
|
input [0:0] RX_ST_VALID,
|
|
output RX_ST_READY,
|
|
input [0:0] RX_ST_EMPTY,
|
|
|
|
// Interface: Altera TX
|
|
output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA,
|
|
output [0:0] TX_ST_VALID,
|
|
input TX_ST_READY,
|
|
output [0:0] TX_ST_EOP,
|
|
output [0:0] TX_ST_SOP,
|
|
output [0:0] TX_ST_EMPTY,
|
|
|
|
// Interface: Altera Config
|
|
input [`SIG_CFG_CTL_W-1:0] TL_CFG_CTL,
|
|
input [`SIG_CFG_ADD_W-1:0] TL_CFG_ADD,
|
|
input [`SIG_CFG_STS_W-1:0] TL_CFG_STS,
|
|
|
|
// Interface: Altera Flow Control
|
|
input [`SIG_FC_CPLH_W-1:0] KO_CPL_SPC_HEADER,
|
|
input [`SIG_FC_CPLD_W-1:0] KO_CPL_SPC_DATA,
|
|
|
|
// Interface: Altera Interrupt
|
|
input APP_MSI_ACK,
|
|
output APP_MSI_REQ,
|
|
|
|
// Interface: RX Classic
|
|
output [C_PCI_DATA_WIDTH-1:0] RX_TLP,
|
|
output RX_TLP_VALID,
|
|
output RX_TLP_START_FLAG,
|
|
output [`SIG_OFFSET_W-1:0] RX_TLP_START_OFFSET,
|
|
output RX_TLP_END_FLAG,
|
|
output [`SIG_OFFSET_W-1:0] RX_TLP_END_OFFSET,
|
|
output [`SIG_BARDECODE_W-1:0] RX_TLP_BAR_DECODE,
|
|
input RX_TLP_READY,
|
|
|
|
// Interface: TX Classic
|
|
output TX_TLP_READY,
|
|
input [C_PCI_DATA_WIDTH-1:0] TX_TLP,
|
|
input TX_TLP_VALID,
|
|
input TX_TLP_START_FLAG,
|
|
input [`SIG_OFFSET_W-1:0] TX_TLP_START_OFFSET,
|
|
input TX_TLP_END_FLAG,
|
|
input [`SIG_OFFSET_W-1:0] TX_TLP_END_OFFSET,
|
|
|
|
// Interface: Configuration
|
|
output [`SIG_CPLID_W-1:0] CONFIG_COMPLETER_ID,
|
|
output CONFIG_BUS_MASTER_ENABLE,
|
|
output [`SIG_LINKWIDTH_W-1:0] CONFIG_LINK_WIDTH,
|
|
output [`SIG_LINKRATE_W-1:0] CONFIG_LINK_RATE,
|
|
output [`SIG_MAXREAD_W-1:0] CONFIG_MAX_READ_REQUEST_SIZE,
|
|
output [`SIG_MAXPAYLOAD_W-1:0] CONFIG_MAX_PAYLOAD_SIZE,
|
|
output CONFIG_INTERRUPT_MSIENABLE,
|
|
output CONFIG_CPL_BOUNDARY_SEL,
|
|
output [`SIG_FC_CPLD_W-1:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data
|
|
output [`SIG_FC_CPLH_W-1:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers
|
|
|
|
// Interface: Interrupt
|
|
output INTR_MSI_RDY, // High when interrupt is able to be sent
|
|
input INTR_MSI_REQUEST // High to request interrupt
|
|
);
|
|
|
|
localparam C_ALTERA_TX_READY_LATENCY = 1;// TODO: HMmmmmm 2?
|
|
localparam C_OFFSET_WIDTH = clog2s(C_PCI_DATA_WIDTH/32);
|
|
|
|
reg [C_PCI_DATA_WIDTH-1:0] rRxStData;
|
|
reg rRxStValid;
|
|
reg rRxStEop;
|
|
reg rRxStSop;
|
|
|
|
reg [`SIG_CFG_ADD_W-1:0] rTlCfgAdd,_rTlCfgAdd;
|
|
reg [`SIG_CFG_CTL_W-1:0] rTlCfgCtl,_rTlCfgCtl;
|
|
reg [`SIG_CFG_STS_W-1:0] rTlCfgSts,_rTlCfgSts;
|
|
|
|
reg [`SIG_CPLID_W-1:0] rCfgCompleterId;
|
|
reg rCfgBusMstrEnable;
|
|
reg [`SIG_MAXREAD_W-1:0] rCfgMaxReadRequestSize;
|
|
reg [`SIG_MAXPAYLOAD_W-1:0] rCfgMaxPayloadSize;
|
|
reg rCfgInterruptMsienable;
|
|
reg rReadCompletionBoundarySel;
|
|
|
|
reg [C_ALTERA_TX_READY_LATENCY-1:0] rTxStReady, _rTxStReady;
|
|
|
|
// Rx Interface (To PCIe Core)
|
|
assign RX_ST_READY = RX_TLP_READY;
|
|
|
|
// Rx Interface (From PCIe Core)
|
|
assign RX_TLP = RX_ST_DATA;
|
|
assign RX_TLP_VALID = RX_ST_VALID;
|
|
assign RX_TLP_END_FLAG = RX_ST_EOP;
|
|
assign RX_TLP_END_OFFSET = {3'b000,RX_ST_EMPTY};
|
|
assign RX_TLP_START_FLAG = RX_ST_SOP;
|
|
assign RX_TLP_START_OFFSET = 0;
|
|
|
|
// TX Interface (From PCIe Core)
|
|
assign TX_TLP_READY = rTxStReady[C_ALTERA_TX_READY_LATENCY-1];
|
|
|
|
// TX Interface (To PCIe Core)
|
|
assign TX_ST_DATA = TX_TLP;
|
|
assign TX_ST_VALID = TX_TLP_VALID & TX_TLP_READY;
|
|
assign TX_ST_EOP = TX_TLP_END_FLAG;
|
|
assign TX_ST_SOP = TX_TLP_START_FLAG;
|
|
|
|
// Configuration Interface
|
|
assign CONFIG_COMPLETER_ID = rCfgCompleterId;
|
|
assign CONFIG_BUS_MASTER_ENABLE = rCfgBusMstrEnable;
|
|
assign CONFIG_LINK_WIDTH = rTlCfgSts[`TLSTS_LWIDTH_R];
|
|
assign CONFIG_LINK_RATE = rTlCfgSts[`TLSTS_LRATE_R];
|
|
assign CONFIG_MAX_READ_REQUEST_SIZE = rCfgMaxReadRequestSize;
|
|
assign CONFIG_MAX_PAYLOAD_SIZE = rCfgMaxPayloadSize;
|
|
assign CONFIG_INTERRUPT_MSIENABLE = rCfgInterruptMsienable;
|
|
assign CONFIG_CPL_BOUNDARY_SEL = rReadCompletionBoundarySel;
|
|
assign CONFIG_MAX_CPL_HDR = KO_CPL_SPC_HEADER;
|
|
assign CONFIG_MAX_CPL_DATA = KO_CPL_SPC_DATA;
|
|
|
|
// Interrupt interface
|
|
assign APP_MSI_REQ = INTR_MSI_REQUEST;
|
|
assign INTR_MSI_RDY = APP_MSI_ACK;
|
|
|
|
always @(*) begin
|
|
_rTxStReady = (rTxStReady << 1) | TX_ST_READY;
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
rTxStReady <= _rTxStReady;
|
|
end
|
|
|
|
always @(*) begin
|
|
_rTlCfgCtl = TL_CFG_CTL;
|
|
_rTlCfgAdd = TL_CFG_ADD;
|
|
_rTlCfgSts = TL_CFG_STS;
|
|
end
|
|
|
|
always @(posedge CLK) begin // Should be the same clock as pld_clk
|
|
rTlCfgAdd <= _rTlCfgAdd;
|
|
rTlCfgCtl <= _rTlCfgCtl;
|
|
rTlCfgSts <= _rTlCfgSts;
|
|
|
|
if(rTlCfgAdd == `TLCFG_DEVCTL_I) begin
|
|
rCfgMaxReadRequestSize <= rTlCfgCtl[`TLCTL_MAXREQ_R];
|
|
rCfgMaxPayloadSize <= rTlCfgCtl[`TLCTL_MAXPAY_R];
|
|
end
|
|
|
|
if(rTlCfgAdd == `TLCFG_LNKCTL_I) begin
|
|
rReadCompletionBoundarySel <= rTlCfgCtl[`TLCTL_RCB_R];
|
|
end
|
|
if(rTlCfgAdd == `TLCFG_PRMCMD_I) begin
|
|
rCfgBusMstrEnable <= rTlCfgCtl[`TLCTL_BUSMSTR_R];
|
|
end
|
|
if(rTlCfgAdd == `TLCFG_MSICSR_I) begin
|
|
rCfgInterruptMsienable <= rTlCfgCtl[`TLCTL_MSIENABLE_R];
|
|
end
|
|
if(rTlCfgAdd == `TLCFG_BUSDEV_I) begin
|
|
rCfgCompleterId <= {rTlCfgCtl[`TLCTL_BUSDEV_R],3'b0};
|
|
end
|
|
end // always @ (posedge CLK)
|
|
generate
|
|
if (C_PCI_DATA_WIDTH == 9'd32) begin : a32
|
|
// Not possible...
|
|
end else if (C_PCI_DATA_WIDTH == 9'd64) begin : a64
|
|
assign TX_ST_EMPTY = 0;
|
|
end else if (C_PCI_DATA_WIDTH == 9'd128) begin : a128
|
|
assign TX_ST_EMPTY = ~TX_TLP_END_OFFSET[1] & TX_ST_EOP;
|
|
end else if (C_PCI_DATA_WIDTH == 9'd256) begin : a256
|
|
assign TX_ST_EMPTY = TX_TLP_END_OFFSET[2];
|
|
end
|
|
endgenerate
|
|
endmodule // translation_layer
|
|
|