From 778c42e74b23f542e7523f99e6f13558dd3fbfef Mon Sep 17 00:00:00 2001 From: Dustin Richmond Date: Mon, 18 Jul 2016 16:28:11 -0700 Subject: [PATCH] First attempt (and maybe only) at fixing a bug in the CHNL_TX interface. In the interface, CHNL_TX_DATA_REN was remaining asserted for two cycles after CHNL_TX was deasserted. This has been fixed, and CHNL_TX_DATA_REN now deasserts one cycle after CHNL_TX is deasserted. --- fpga/riffa_hdl/tx_port_channel_gate_128.v | 334 ++++++++++----------- fpga/riffa_hdl/tx_port_channel_gate_32.v | 339 ++++++++++------------ fpga/riffa_hdl/tx_port_channel_gate_64.v | 334 ++++++++++----------- 3 files changed, 474 insertions(+), 533 deletions(-) diff --git a/fpga/riffa_hdl/tx_port_channel_gate_128.v b/fpga/riffa_hdl/tx_port_channel_gate_128.v index 0885389..42b4649 100644 --- a/fpga/riffa_hdl/tx_port_channel_gate_128.v +++ b/fpga/riffa_hdl/tx_port_channel_gate_128.v @@ -33,189 +33,169 @@ // DAMAGE. // ---------------------------------------------------------------------- //---------------------------------------------------------------------------- -// Filename: tx_port_channel_gate_128.v -// Version: 1.00.a -// Verilog Standard: Verilog-2001 -// Description: Captures transaction open/close events as well as data +// Filename: tx_port_channel_gate_128.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 +// Author: Matt Jacobsen +// History: @mattj: Version 2.0 //----------------------------------------------------------------------------- -`define S_TXPORTGATE128_IDLE 2'b00 -`define S_TXPORTGATE128_OPENING 2'b01 -`define S_TXPORTGATE128_OPEN 2'b10 -`define S_TXPORTGATE128_CLOSED 2'b11 +`define S_TXPORTGATE128_IDLE 2'b00 +`define S_TXPORTGATE128_OPENING 2'b01 +`define S_TXPORTGATE128_OPEN 2'b10 +`define S_TXPORTGATE128_CLOSED 2'b11 `timescale 1ns/1ns -module tx_port_channel_gate_128 #( - parameter C_DATA_WIDTH = 9'd128, - // 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_TXPORTGATE128_IDLE, _rState=`S_TXPORTGATE128_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_TXPORTGATE128_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_TXPORTGATE128_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_TXPORTGATE128_IDLE: begin // Write the len, off, last - _rPause = 0; - _rClosed = 0; - if (!wFifoFull) begin - _rAck = rChnlTx; - _rFifoWen = rChnlTx; - _rFifoData = {1'd1, 64'd0, rChnlLen, rChnlOff, rChnlLast}; - if (rChnlTx) - _rState = `S_TXPORTGATE128_OPENING; - end - end - - `S_TXPORTGATE128_OPENING: begin // Write the len, off, last (again) - _rAck = 0; - _rClosed = (rClosed | !rChnlTx); - if (!wFifoFull) begin - if (rClosed | !rChnlTx) - _rState = `S_TXPORTGATE128_CLOSED; - else - _rState = `S_TXPORTGATE128_OPEN; - end - end - - `S_TXPORTGATE128_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_TXPORTGATE128_CLOSED; - end - - `S_TXPORTGATE128_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_TXPORTGATE128_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 -); -*/ +module tx_port_channel_gate_128 + #(parameter C_DATA_WIDTH = 9'd128, + // 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_TXPORTGATE128_IDLE, _rState=`S_TXPORTGATE128_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; + reg rOpen=0, _rOpen=0; + + assign CHNL_TX_ACK = rAck; + assign CHNL_TX_DATA_REN = (rOpen & !wFifoFull); // S_TXPORTGATE128_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_TXPORTGATE128_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); + rOpen <= #1 (RST ? 1'd0 : _rOpen); + end + + always @ (*) begin + _rState = rState; + _rFifoWen = rFifoWen; + _rFifoData = rFifoData; + _rPause = rPause; + _rAck = rAck; + _rClosed = rClosed; + _rOpen = rOpen; + case (rState) + + `S_TXPORTGATE128_IDLE: begin // Write the len, off, last + _rPause = 0; + _rClosed = 0; + _rOpen = 0; + if (!wFifoFull) begin + _rAck = rChnlTx; + _rFifoWen = rChnlTx; + _rFifoData = {1'd1, 64'd0, rChnlLen, rChnlOff, rChnlLast}; + if (rChnlTx) + _rState = `S_TXPORTGATE128_OPENING; + end + end + + `S_TXPORTGATE128_OPENING: begin // Write the len, off, last (again) + _rAck = 0; + // rClosed catches a transfer that opens and subsequently closes + // without writing data + _rClosed = (rClosed | !rChnlTx); + if (!wFifoFull) begin + if (rClosed | !rChnlTx) + _rState = `S_TXPORTGATE128_CLOSED; + else begin + _rState = `S_TXPORTGATE128_OPEN; + _rOpen = CHNL_TX & rChnlTx; + end + end + end + + `S_TXPORTGATE128_OPEN: begin // Copy channel data into the FIFO + if (!wFifoFull) begin + // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered + // but the VALID+REN model seem to make this difficult. + _rFifoWen = CHNL_TX_DATA_VALID; + _rFifoData = {1'd0, CHNL_TX_DATA}; + end + if (!rChnlTx) + _rState = `S_TXPORTGATE128_CLOSED; + _rOpen = CHNL_TX & rChnlTx; + end + + `S_TXPORTGATE128_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_TXPORTGATE128_IDLE; + end + end + + endcase + end endmodule diff --git a/fpga/riffa_hdl/tx_port_channel_gate_32.v b/fpga/riffa_hdl/tx_port_channel_gate_32.v index 98314e1..1256d24 100644 --- a/fpga/riffa_hdl/tx_port_channel_gate_32.v +++ b/fpga/riffa_hdl/tx_port_channel_gate_32.v @@ -33,191 +33,172 @@ // DAMAGE. // ---------------------------------------------------------------------- //---------------------------------------------------------------------------- -// Filename: tx_port_channel_gate_32.v -// Version: 1.00.a -// Verilog Standard: Verilog-2001 -// Description: Captures transaction open/close events as well as data +// Filename: tx_port_channel_gate_32.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 +// Author: Matt Jacobsen +// History: @mattj: Version 2.0 //----------------------------------------------------------------------------- -`define S_TXPORTGATE32_IDLE 2'b00 -`define S_TXPORTGATE32_OPENING 2'b01 -`define S_TXPORTGATE32_OPEN 2'b10 -`define S_TXPORTGATE32_CLOSED 2'b11 +`define S_TXPORTGATE32_IDLE 2'b00 +`define S_TXPORTGATE32_OPENING 2'b01 +`define S_TXPORTGATE32_OPEN 2'b10 +`define S_TXPORTGATE32_CLOSED 2'b11 `timescale 1ns/1ns -module tx_port_channel_gate_32 #( - parameter C_DATA_WIDTH = 9'd32, - // 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_TXPORTGATE32_IDLE, _rState=`S_TXPORTGATE32_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_TXPORTGATE32_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_TXPORTGATE32_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_TXPORTGATE32_IDLE: begin // Write the len - _rPause = 0; - _rClosed = 0; - if (!wFifoFull) begin - _rFifoWen = rChnlTx; - _rFifoData = {1'd1, rChnlLen}; - if (rChnlTx) - _rState = `S_TXPORTGATE32_OPENING; - end - end - - `S_TXPORTGATE32_OPENING: begin // Write the off, last - _rClosed = (rClosed | !rChnlTx); - if (!wFifoFull) begin - _rAck = rChnlTx; - _rFifoData = {1'd1, rChnlOff, rChnlLast}; - if (rClosed | !rChnlTx) - _rState = `S_TXPORTGATE32_CLOSED; - else - _rState = `S_TXPORTGATE32_OPEN; - end - end - - `S_TXPORTGATE32_OPEN: begin // Copy channel data into the FIFO - _rAck = 0; - 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_TXPORTGATE32_CLOSED; - end - - `S_TXPORTGATE32_CLOSED: begin // Write the end marker (twice) - _rAck = 0; - if (!wFifoFull) begin - _rPause = 1; - _rFifoWen = 1; - _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; - if (rPause) - _rState = `S_TXPORTGATE32_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 -); -*/ +module tx_port_channel_gate_32 + #(parameter C_DATA_WIDTH = 9'd32, + // 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_TXPORTGATE32_IDLE, _rState=`S_TXPORTGATE32_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; + reg rOpen=0, _rOpen=0; + + assign CHNL_TX_ACK = rAck; + assign CHNL_TX_DATA_REN = (rOpen & !wFifoFull); // S_TXPORTGATE32_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_TXPORTGATE32_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); + rOpen <= #1 (RST ? 1'd0 : _rOpen); + end + + always @ (*) begin + _rState = rState; + _rFifoWen = rFifoWen; + _rFifoData = rFifoData; + _rPause = rPause; + _rAck = rAck; + _rClosed = rClosed; + _rOpen = rOpen; + case (rState) + + `S_TXPORTGATE32_IDLE: begin // Write the len + _rPause = 0; + _rClosed = 0; + _rOpen = 0; + if (!wFifoFull) begin + _rFifoWen = rChnlTx; + _rFifoData = {1'd1, rChnlLen}; + if (rChnlTx) + _rState = `S_TXPORTGATE32_OPENING; + end + end + + `S_TXPORTGATE32_OPENING: begin // Write the off, last + // rClosed catches a transfer that opens and subsequently closes + // without writing data + _rClosed = (rClosed | !rChnlTx); + if (!wFifoFull) begin + _rAck = rChnlTx; + _rFifoData = {1'd1, rChnlOff, rChnlLast}; + if (rClosed | !rChnlTx) + _rState = `S_TXPORTGATE32_CLOSED; + else begin + _rState = `S_TXPORTGATE32_OPEN; + _rOpen = CHNL_TX & rChnlTx; + end + end + end + + `S_TXPORTGATE32_OPEN: begin // Copy channel data into the FIFO + _rAck = 0; + if (!wFifoFull) begin + // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered + // but the VALID+REN model seem to make this difficult. + _rFifoWen = CHNL_TX_DATA_VALID; + _rFifoData = {1'd0, CHNL_TX_DATA}; + end + if (!rChnlTx) + _rState = `S_TXPORTGATE32_CLOSED; + _rOpen = CHNL_TX & rChnlTx; + end + + `S_TXPORTGATE32_CLOSED: begin // Write the end marker (twice) + _rAck = 0; + if (!wFifoFull) begin + _rPause = 1; + _rFifoWen = 1; + _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; + if (rPause) + _rState = `S_TXPORTGATE32_IDLE; + end + end + + endcase + + end endmodule diff --git a/fpga/riffa_hdl/tx_port_channel_gate_64.v b/fpga/riffa_hdl/tx_port_channel_gate_64.v index 4e5712a..bd9ef0e 100644 --- a/fpga/riffa_hdl/tx_port_channel_gate_64.v +++ b/fpga/riffa_hdl/tx_port_channel_gate_64.v @@ -33,189 +33,169 @@ // 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 +// 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 +// 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 +`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 -); -*/ +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; + reg rOpen=0, _rOpen=0; + + assign CHNL_TX_ACK = rAck; + assign CHNL_TX_DATA_REN = (rOpen & !wFifoFull); // S_TXPORTGATE128_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); + rOpen <= #1 (RST ? 1'd0 : _rOpen); + end + + always @ (*) begin + _rState = rState; + _rFifoWen = rFifoWen; + _rFifoData = rFifoData; + _rPause = rPause; + _rAck = rAck; + _rClosed = rClosed; + _rOpen = rOpen; + case (rState) + + `S_TXPORTGATE64_IDLE: begin // Write the len, off, last + _rPause = 0; + _rClosed = 0; + _rOpen = 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 catches a transfer that opens and subsequently closes + // without writing data + _rClosed = (rClosed | !rChnlTx); + if (!wFifoFull) begin + if (rClosed | !rChnlTx) + _rState = `S_TXPORTGATE64_CLOSED; + else begin + _rState = `S_TXPORTGATE64_OPEN; + _rOpen = CHNL_TX & rChnlTx; + end + end + end + + `S_TXPORTGATE64_OPEN: begin // Copy channel data into the FIFO + if (!wFifoFull) begin + // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered + // but the VALID+REN model seem to make this difficult. + _rFifoWen = CHNL_TX_DATA_VALID; + _rFifoData = {1'd0, CHNL_TX_DATA}; + end + if (!rChnlTx) + _rState = `S_TXPORTGATE64_CLOSED; + _rOpen = CHNL_TX & rChnlTx; + 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 endmodule