2015-05-04 14:50:57 -07:00
|
|
|
// ----------------------------------------------------------------------
|
2016-02-09 15:23:37 -08:00
|
|
|
// Copyright (c) 2016, The Regents of the University of California All
|
2015-05-04 14:50:57 -07:00
|
|
|
// 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_data_pipeline.v
|
|
|
|
// Version: 1.0
|
|
|
|
// Verilog Standard: Verilog-2001
|
|
|
|
//
|
|
|
|
// Description: The tx_data_fifo takes 0-bit aligned packet data and
|
|
|
|
// puts each DW into one of N FIFOs where N = (C_DATA_WIDTH/32).
|
|
|
|
//
|
|
|
|
// The data interface (TX_DATA) is an interface for N 32-bit FIFOs, where N =
|
|
|
|
// (C_DATA_WIDTH/32). The START_FLAG signal indicates that the first dword of
|
|
|
|
// a packet is in FIFO 0 (TX_DATA[31:0]). Each FIFO interface also contains an
|
|
|
|
// END_FLAG signal in the END_FLAGS bus. When a bit in END_FLAGS bus is asserted,
|
|
|
|
// its corresponding fifo contains the last dword of data for the current
|
|
|
|
// packet. START_FLAG, END_FLAG and DATA are all qualified by the VALID signal,
|
|
|
|
// and read by the READY signal.
|
|
|
|
//
|
|
|
|
// The write interface (WR_TX) differs slightly from the read interface because it
|
|
|
|
// produces a READY signal and consumes a VALID signal. VALID is asserted when an
|
|
|
|
// entire packet has been packed into a FIFO.
|
|
|
|
//
|
|
|
|
// TODO:
|
|
|
|
// - Make sure that the synthesis tool is removing the other three start
|
|
|
|
// flag wires (and modifying the width of the FIFOs)
|
|
|
|
//
|
|
|
|
// Author: Dustin Richmond (@darichmond)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
`timescale 1ns/1ns
|
|
|
|
`include "trellis.vh" // Defines the user-facing signal widths.
|
|
|
|
module tx_data_fifo
|
|
|
|
#(parameter C_DEPTH_PACKETS = 10,
|
|
|
|
parameter C_DATA_WIDTH = 128,
|
|
|
|
parameter C_PIPELINE_INPUT = 1,
|
2015-07-29 08:33:11 -07:00
|
|
|
parameter C_MAX_PAYLOAD_DWORDS = 256)
|
|
|
|
(// Interface: Clocks
|
2015-05-04 14:50:57 -07:00
|
|
|
input CLK,
|
|
|
|
|
|
|
|
// Interface: Reset
|
|
|
|
input RST_IN,
|
|
|
|
|
|
|
|
// Interface: WR TX DATA
|
|
|
|
input [C_DATA_WIDTH-1:0] WR_TX_DATA,
|
|
|
|
input WR_TX_DATA_VALID,
|
|
|
|
input WR_TX_DATA_START_FLAG,
|
|
|
|
input [(C_DATA_WIDTH/32)-1:0] WR_TX_DATA_WORD_VALID,
|
|
|
|
input [(C_DATA_WIDTH/32)-1:0] WR_TX_DATA_END_FLAGS,
|
|
|
|
output WR_TX_DATA_READY,
|
|
|
|
|
|
|
|
// Interface: RD TX DATA
|
|
|
|
input [(C_DATA_WIDTH/32)-1:0] RD_TX_DATA_WORD_READY,
|
|
|
|
output [C_DATA_WIDTH-1:0] RD_TX_DATA,
|
|
|
|
output RD_TX_DATA_START_FLAG,
|
|
|
|
output [(C_DATA_WIDTH/32)-1:0] RD_TX_DATA_END_FLAGS,
|
|
|
|
output [(C_DATA_WIDTH/32)-1:0] RD_TX_DATA_WORD_VALID,
|
2015-07-29 08:33:11 -07:00
|
|
|
output RD_TX_DATA_PACKET_VALID);
|
|
|
|
|
2015-05-04 14:50:57 -07:00
|
|
|
localparam C_FIFO_OUTPUT_DEPTH = 1;
|
|
|
|
localparam C_INPUT_DEPTH = C_PIPELINE_INPUT != 0 ? 1 : 0;
|
2015-07-29 08:33:11 -07:00
|
|
|
localparam C_PAYLOAD_DEPTH = (C_MAX_PAYLOAD_DWORDS*32)/C_DATA_WIDTH;
|
|
|
|
localparam C_FIFO_DEPTH = C_PAYLOAD_DEPTH*C_DEPTH_PACKETS;
|
|
|
|
localparam C_FIFO_DATA_WIDTH = 32; // 1 DW, End Flag, Start Flag
|
|
|
|
localparam C_FIFO_WIDTH = 32 + 2; // 1 DW, End Flag, Start Flag
|
|
|
|
localparam C_INOUT_REG_WIDTH = C_FIFO_WIDTH;
|
2015-05-04 14:50:57 -07:00
|
|
|
localparam C_NUM_FIFOS = (C_DATA_WIDTH/32);
|
|
|
|
genvar i;
|
|
|
|
|
|
|
|
wire RST;
|
|
|
|
|
|
|
|
wire [C_FIFO_DATA_WIDTH-1:0] wWrTxData[C_NUM_FIFOS-1:0];
|
|
|
|
wire [C_NUM_FIFOS-1:0] wWrTxDataValid;
|
2015-07-30 13:35:48 -07:00
|
|
|
wire [C_NUM_FIFOS-1:0] wWrTxDataReady, _wWrTxDataReady;
|
2015-05-04 14:50:57 -07:00
|
|
|
wire [C_NUM_FIFOS-1:0] wWrTxDataStartFlags;
|
|
|
|
wire [C_NUM_FIFOS-1:0] wWrTxDataEndFlags;
|
|
|
|
|
|
|
|
wire [C_NUM_FIFOS-1:0] _wRdTxDataStartFlags;
|
|
|
|
|
|
|
|
wire [C_FIFO_DATA_WIDTH-1:0] wRdTxData[C_NUM_FIFOS-1:0];
|
|
|
|
wire [C_NUM_FIFOS-1:0] wRdTxDataValid;
|
|
|
|
wire [C_NUM_FIFOS-1:0] wRdTxDataReady;
|
|
|
|
wire [C_NUM_FIFOS-1:0] wRdTxDataStartFlags;
|
|
|
|
wire [C_NUM_FIFOS-1:0] wRdTxDataEndFlags;
|
|
|
|
wire wRdTxDataPacketValid;
|
|
|
|
|
|
|
|
wire wWrTxEndFlagValid;
|
|
|
|
wire wWrTxEndFlagReady;
|
|
|
|
|
|
|
|
wire wRdTxEndFlagValid;
|
|
|
|
wire wRdTxEndFlagReady;
|
|
|
|
|
|
|
|
wire wPacketDecrement;
|
|
|
|
wire wPacketIncrement;
|
|
|
|
|
2016-02-02 17:14:29 -08:00
|
|
|
//reg [clog2(C_DEPTH_PACKETS+1)-1:0] rPacketCounter,_rPacketCounter;
|
|
|
|
wire [clog2(C_DEPTH_PACKETS+1)-1:0] wPacketCounter;
|
2015-05-04 14:50:57 -07:00
|
|
|
|
2016-02-02 17:14:29 -08:00
|
|
|
wire [C_NUM_FIFOS-1:0] wEFDecrement;
|
|
|
|
wire [C_NUM_FIFOS-1:0] wEFIncrement;
|
|
|
|
wire [clog2(C_DEPTH_PACKETS+1)-1:0] wEFCounter [C_NUM_FIFOS-1:0];
|
|
|
|
wire [C_NUM_FIFOS-1:0] wEFValid;
|
2015-05-04 14:50:57 -07:00
|
|
|
/*AUTOINPUT*/
|
|
|
|
/*AUTOWIRE*/
|
|
|
|
///*AUTOOUTPUT*/
|
|
|
|
|
|
|
|
assign RST = RST_IN;
|
|
|
|
|
|
|
|
assign wWrTxEndFlagValid = (wWrTxDataEndFlags & wWrTxDataValid) != {C_NUM_FIFOS{1'b0}};
|
2016-02-02 17:14:29 -08:00
|
|
|
assign wWrTxEndFlagReady = wPacketCounter != C_DEPTH_PACKETS;// Designed a small bit of latency here to help timing...
|
2015-05-04 14:50:57 -07:00
|
|
|
assign wPacketIncrement = wWrTxEndFlagValid & wWrTxEndFlagReady;
|
|
|
|
assign wPacketDecrement = wRdTxEndFlagValid & wRdTxEndFlagReady;
|
|
|
|
|
2015-07-30 13:35:48 -07:00
|
|
|
assign WR_TX_DATA_READY = _wWrTxDataReady[0];
|
2015-05-04 14:50:57 -07:00
|
|
|
|
2016-02-02 17:14:29 -08:00
|
|
|
assign wRdTxEndFlagValid = wPacketCounter != 0;
|
2015-05-04 14:50:57 -07:00
|
|
|
assign wRdTxEndFlagReady = (wRdTxDataReady & wRdTxDataEndFlags & wRdTxDataValid) != {C_NUM_FIFOS{1'b0}};
|
2016-02-02 17:14:29 -08:00
|
|
|
assign wRdTxDataPacketValid = wPacketCounter != 0;
|
2015-05-04 14:50:57 -07:00
|
|
|
|
|
|
|
assign RD_TX_DATA_START_FLAG = _wRdTxDataStartFlags[0];
|
|
|
|
|
2016-02-02 17:14:29 -08:00
|
|
|
counter_v2
|
|
|
|
#(// Parameters
|
|
|
|
.C_MAX_VALUE (C_DEPTH_PACKETS),
|
|
|
|
.C_SAT_VALUE (C_DEPTH_PACKETS + 1), // Never saturate
|
|
|
|
.C_RST_VALUE (0),
|
|
|
|
.C_FLR_VALUE (0)
|
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
packet_ctr_inst
|
|
|
|
(// Outputs
|
|
|
|
.VALUE (wPacketCounter),
|
|
|
|
// Inputs
|
|
|
|
.INC (wPacketIncrement),
|
|
|
|
.DEC (wPacketDecrement),
|
|
|
|
/*AUTOINST*/
|
|
|
|
// Inputs
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST_IN (RST_IN));
|
|
|
|
|
2015-05-04 14:50:57 -07:00
|
|
|
|
|
|
|
generate
|
|
|
|
for( i = 0 ; i < C_NUM_FIFOS ; i = i + 1 ) begin : gen_regs_fifos
|
|
|
|
pipeline
|
|
|
|
#(
|
|
|
|
.C_DEPTH (C_INPUT_DEPTH),
|
|
|
|
.C_USE_MEMORY (0),
|
2015-07-29 08:33:11 -07:00
|
|
|
.C_WIDTH (C_INOUT_REG_WIDTH)
|
2015-05-04 14:50:57 -07:00
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
input_pipeline_inst_
|
|
|
|
(
|
|
|
|
// Outputs
|
2015-07-30 13:35:48 -07:00
|
|
|
.WR_DATA_READY (_wWrTxDataReady[i]),
|
2015-05-04 14:50:57 -07:00
|
|
|
.RD_DATA ({wWrTxData[i], wWrTxDataEndFlags[i],wWrTxDataStartFlags[i]}),
|
|
|
|
.RD_DATA_VALID (wWrTxDataValid[i]),
|
|
|
|
// Inputs
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST_IN (RST_IN),
|
|
|
|
.WR_DATA ({WR_TX_DATA[C_FIFO_DATA_WIDTH*i +: C_FIFO_DATA_WIDTH],
|
|
|
|
WR_TX_DATA_END_FLAGS[i], (i == 0) ? WR_TX_DATA_START_FLAG: 1'b0}),
|
|
|
|
.WR_DATA_VALID (WR_TX_DATA_VALID & WR_TX_DATA_WORD_VALID[i]),
|
|
|
|
.RD_DATA_READY (wWrTxDataReady[i]));
|
|
|
|
|
|
|
|
fifo
|
|
|
|
#(
|
|
|
|
// Parameters
|
|
|
|
.C_WIDTH (C_FIFO_WIDTH),
|
|
|
|
.C_DEPTH (C_FIFO_DEPTH),
|
|
|
|
.C_DELAY (0)
|
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
fifo_inst_
|
|
|
|
(
|
|
|
|
// Outputs
|
|
|
|
.RD_DATA ({wRdTxData[i], wRdTxDataStartFlags[i], wRdTxDataEndFlags[i]}),
|
|
|
|
.WR_READY (wWrTxDataReady[i]),
|
|
|
|
.RD_VALID (wRdTxDataValid[i]),
|
|
|
|
// Inputs
|
|
|
|
.WR_DATA ({wWrTxData[i], wWrTxDataStartFlags[i], wWrTxDataEndFlags[i]}),
|
|
|
|
.WR_VALID (wWrTxDataValid[i]),
|
|
|
|
.RD_READY (wRdTxDataReady[i]),
|
|
|
|
/*AUTOINST*/
|
|
|
|
// Inputs
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST (RST));
|
|
|
|
|
|
|
|
pipeline
|
|
|
|
#(
|
|
|
|
.C_DEPTH (C_FIFO_OUTPUT_DEPTH),
|
|
|
|
.C_USE_MEMORY (0),
|
|
|
|
.C_WIDTH (C_FIFO_WIDTH)
|
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
fifo_pipeline_inst_
|
|
|
|
(
|
|
|
|
// Outputs
|
|
|
|
.WR_DATA_READY (wRdTxDataReady[i]),
|
|
|
|
.RD_DATA ({RD_TX_DATA[i*32 +: 32],
|
|
|
|
_wRdTxDataStartFlags[i],
|
|
|
|
RD_TX_DATA_END_FLAGS[i]}),
|
|
|
|
.RD_DATA_VALID (RD_TX_DATA_WORD_VALID[i]),
|
|
|
|
// Inputs
|
|
|
|
.WR_DATA ({wRdTxData[i],
|
|
|
|
wRdTxDataStartFlags[i],
|
|
|
|
wRdTxDataEndFlags[i]}),
|
|
|
|
.WR_DATA_VALID (wRdTxDataValid[i]),
|
|
|
|
.RD_DATA_READY (RD_TX_DATA_WORD_READY[i]),
|
|
|
|
/*AUTOINST*/
|
|
|
|
// Inputs
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST_IN (RST_IN));
|
2016-02-02 17:14:29 -08:00
|
|
|
|
|
|
|
assign wEFIncrement[i] = wWrTxDataEndFlags[i] & wWrTxDataValid[i];
|
|
|
|
assign wEFDecrement[i] = wRdTxDataEndFlags[i] & wRdTxDataReady[i];
|
|
|
|
assign wEFValid[i] = (wEFCounter[i] != 0);
|
|
|
|
|
|
|
|
counter_v2
|
|
|
|
#(// Parameters
|
|
|
|
.C_MAX_VALUE (C_DEPTH_PACKETS),
|
|
|
|
.C_SAT_VALUE (C_DEPTH_PACKETS + 1), // Never saturate
|
|
|
|
.C_RST_VALUE (0),
|
|
|
|
.C_FLR_VALUE (0)
|
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
perfifo_ctr_inst
|
|
|
|
(// Outputs
|
|
|
|
.VALUE (wEFCounter[i]),
|
|
|
|
// Inputs
|
|
|
|
.INC (wEFIncrement[i]),
|
|
|
|
.DEC (wEFDecrement[i]),
|
|
|
|
/*AUTOINST*/
|
|
|
|
// Inputs
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST_IN (RST_IN));
|
|
|
|
|
2015-05-04 14:50:57 -07:00
|
|
|
end // for ( i = 0 ; i < C_NUM_FIFOS ; i = i + 1 )
|
2015-07-22 17:29:35 -07:00
|
|
|
pipeline
|
|
|
|
#(.C_DEPTH (C_FIFO_OUTPUT_DEPTH),
|
|
|
|
.C_USE_MEMORY (0),
|
|
|
|
.C_WIDTH (1)
|
|
|
|
/*AUTOINSTPARAM*/)
|
|
|
|
packet_valid_reg
|
|
|
|
(// Outputs
|
|
|
|
.WR_DATA_READY (),
|
|
|
|
.RD_DATA (),
|
|
|
|
.RD_DATA_VALID (RD_TX_DATA_PACKET_VALID),
|
|
|
|
// Inputs
|
|
|
|
.WR_DATA (),
|
2016-02-02 17:14:29 -08:00
|
|
|
.WR_DATA_VALID (wEFValid != 0),
|
|
|
|
.RD_DATA_READY ((RD_TX_DATA_WORD_READY & RD_TX_DATA_END_FLAGS) != 0),
|
2015-07-22 17:29:35 -07:00
|
|
|
/*AUTOINST*/
|
|
|
|
// Inputs
|
2016-02-02 17:14:29 -08:00
|
|
|
.CLK (CLK),
|
|
|
|
.RST_IN (RST_IN));
|
2015-05-04 14:50:57 -07:00
|
|
|
endgenerate
|
|
|
|
endmodule
|
|
|
|
// Local Variables:
|
|
|
|
// verilog-library-directories:("." "../../common/")
|
|
|
|
// End:
|
|
|
|
|
|
|
|
|
2016-02-02 17:14:29 -08:00
|
|
|
module counter_v2
|
|
|
|
#(parameter C_MAX_VALUE = 10,
|
|
|
|
parameter C_SAT_VALUE = 10,
|
|
|
|
parameter C_FLR_VALUE = 0,
|
|
|
|
parameter C_RST_VALUE = 0)
|
|
|
|
(input CLK,
|
|
|
|
input RST_IN,
|
|
|
|
|
|
|
|
input INC,
|
|
|
|
input DEC,
|
|
|
|
output [clog2s(C_MAX_VALUE+1)-1:0] VALUE);
|
|
|
|
|
|
|
|
wire wInc;
|
|
|
|
wire wDec;
|
|
|
|
|
|
|
|
reg [clog2s(C_MAX_VALUE+1)-1:0] wCtrValue;
|
|
|
|
reg [clog2s(C_MAX_VALUE+1)-1:0] rCtrValue;
|
|
|
|
/* verilator lint_off WIDTH */
|
|
|
|
assign wInc = INC & (C_SAT_VALUE > rCtrValue);
|
|
|
|
assign wDec = DEC & (C_FLR_VALUE < rCtrValue);
|
|
|
|
/* verilator lint_on WIDTH */
|
|
|
|
assign VALUE = rCtrValue;
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if(RST_IN) begin
|
|
|
|
rCtrValue <= C_RST_VALUE[clog2s(C_MAX_VALUE+1)-1:0];
|
|
|
|
end else if(wInc & wDec) begin
|
|
|
|
rCtrValue <= rCtrValue + 0;
|
|
|
|
end else if(wInc) begin
|
|
|
|
rCtrValue <= rCtrValue + 1;
|
|
|
|
end else if(wDec) begin
|
|
|
|
rCtrValue <= rCtrValue - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endmodule
|