// ---------------------------------------------------------------------- // 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_port_channel_gate_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Captures transaction open/close events as well as data // and passes it to the RD_CLK domain through the async_fifo. CHNL_TX_DATA_REN can // only be high after CHNL_TX goes high and after the CHNL_TX_ACK pulse. When // CHNL_TX drops, the channel closes (until the next transaction -- signaled by // CHNL_TX going up again). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTGATE64_IDLE 2'b00 `define S_TXPORTGATE64_OPENING 2'b01 `define S_TXPORTGATE64_OPEN 2'b10 `define S_TXPORTGATE64_CLOSED 2'b11 `timescale 1ns/1ns module tx_port_channel_gate_64 #( parameter C_DATA_WIDTH = 9'd64, // Local parameters parameter C_FIFO_DEPTH = 8, parameter C_FIFO_DATA_WIDTH = C_DATA_WIDTH+1 ) ( input RST, input RD_CLK, // FIFO read clock output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // FIFO read data output RD_EMPTY, // FIFO is empty input RD_EN, // FIFO read enable input CHNL_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rState=`S_TXPORTGATE64_IDLE, _rState=`S_TXPORTGATE64_IDLE; reg rFifoWen=0, _rFifoWen=0; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData=0, _rFifoData=0; wire wFifoFull; reg rChnlTx=0, _rChnlTx=0; reg rChnlLast=0, _rChnlLast=0; reg [31:0] rChnlLen=0, _rChnlLen=0; reg [30:0] rChnlOff=0, _rChnlOff=0; reg rAck=0, _rAck=0; reg rPause=0, _rPause=0; reg rClosed=0, _rClosed=0; assign CHNL_TX_ACK = rAck; assign CHNL_TX_DATA_REN = (rState[1] & !rState[0] & !wFifoFull); // S_TXPORTGATE64_OPEN // Buffer the input signals that come from outside the tx_port. always @ (posedge CHNL_CLK) begin rChnlTx <= #1 (RST ? 1'd0 : _rChnlTx); rChnlLast <= #1 _rChnlLast; rChnlLen <= #1 _rChnlLen; rChnlOff <= #1 _rChnlOff; end always @ (*) begin _rChnlTx = CHNL_TX; _rChnlLast = CHNL_TX_LAST; _rChnlLen = CHNL_TX_LEN; _rChnlOff = CHNL_TX_OFF; end // FIFO for temporarily storing data from the channel. (* RAM_STYLE="DISTRIBUTED" *) async_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH)) fifo ( .WR_CLK(CHNL_CLK), .WR_RST(RST), .WR_EN(rFifoWen), .WR_DATA(rFifoData), .WR_FULL(wFifoFull), .RD_CLK(RD_CLK), .RD_RST(RST), .RD_EN(RD_EN), .RD_DATA(RD_DATA), .RD_EMPTY(RD_EMPTY) ); // Pass the transaction open event, transaction data, and the transaction // close event through to the RD_CLK domain via the async_fifo. always @ (posedge CHNL_CLK) begin rState <= #1 (RST ? `S_TXPORTGATE64_IDLE : _rState); rFifoWen <= #1 (RST ? 1'd0 : _rFifoWen); rFifoData <= #1 _rFifoData; rAck <= #1 (RST ? 1'd0 : _rAck); rPause <= #1 (RST ? 1'd0 : _rPause); rClosed <= #1 (RST ? 1'd0 : _rClosed); end always @ (*) begin _rState = rState; _rFifoWen = rFifoWen; _rFifoData = rFifoData; _rPause = rPause; _rAck = rAck; _rClosed = rClosed; case (rState) `S_TXPORTGATE64_IDLE: begin // Write the len, off, last _rPause = 0; _rClosed = 0; if (!wFifoFull) begin _rAck = rChnlTx; _rFifoWen = rChnlTx; _rFifoData = {1'd1, rChnlLen, rChnlOff, rChnlLast}; if (rChnlTx) _rState = `S_TXPORTGATE64_OPENING; end end `S_TXPORTGATE64_OPENING: begin // Write the len, off, last (again) _rAck = 0; _rClosed = (rClosed | !rChnlTx); if (!wFifoFull) begin if (rClosed | !rChnlTx) _rState = `S_TXPORTGATE64_CLOSED; else _rState = `S_TXPORTGATE64_OPEN; end end `S_TXPORTGATE64_OPEN: begin // Copy channel data into the FIFO if (!wFifoFull) begin _rFifoWen = CHNL_TX_DATA_VALID; // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered _rFifoData = {1'd0, CHNL_TX_DATA}; // but the VALID+REN model seem to make this difficult. end if (!rChnlTx) _rState = `S_TXPORTGATE64_CLOSED; end `S_TXPORTGATE64_CLOSED: begin // Write the end marker (twice) if (!wFifoFull) begin _rPause = 1; _rFifoWen = 1; _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; if (rPause) _rState = `S_TXPORTGATE64_IDLE; end end endcase end /* wire [35:0] wControl0; chipscope_icon_1 cs_icon( .CONTROL0(wControl0) ); chipscope_ila_t8_512 a0( .CLK(CHNL_CLK), .CONTROL(wControl0), .TRIG0({4'd0, wFifoFull, CHNL_TX, rState}), .DATA({313'd0, rChnlOff, // 31 rChnlLen, // 32 rChnlLast, // 1 rChnlTx, // 1 CHNL_TX_OFF, // 31 CHNL_TX_LEN, // 32 CHNL_TX_LAST, // 1 CHNL_TX, // 1 wFifoFull, // 1 rFifoData, // 65 rFifoWen, // 1 rState}) // 2 ); */ endmodule