1//
2// Copyright 2011-2012 Ettus Research LLC
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16//
17
18//////////////////////////////////////////////////////////////////////////////////
19
20//this is a FIFO master interface for the FX2 in "slave fifo" mode.
21
22module slave_fifo
23  #(
24        //how many cycles max in a transfer state
25        parameter DATA_XFER_COUNT = 256,
26        parameter CTRL_XFER_COUNT = 32,
27
28        //sizes for fifo36 2 clock cascade fifos
29        parameter DATA_RX_FIFO_SIZE = 9,
30        parameter DATA_TX_FIFO_SIZE = 9,
31        parameter CTRL_RX_FIFO_SIZE = 9,
32        parameter CTRL_TX_FIFO_SIZE = 9
33   )
34   (// GPIF signals
35    input gpif_clk, input gpif_rst,
36    inout [15:0] gpif_d,
37    input [3:0] gpif_ctl,
38    output reg sloe, output reg slrd, output reg slwr, output reg pktend, output reg [1:0] fifoadr,
39
40    // FIFO interface
41    input fifo_clk, input fifo_rst,
42    output [35:0] tx_data, output tx_src_rdy, input tx_dst_rdy,
43    input [35:0] rx_data, input rx_src_rdy, output rx_dst_rdy,
44    output [35:0] ctrl_data, output ctrl_src_rdy, input ctrl_dst_rdy,
45    input [35:0] resp_data, input resp_src_rdy, output resp_dst_rdy,
46
47    output [31:0] debug
48    );
49
50    wire FX2_DE_pre = ~gpif_ctl[0]; //EP2 FX2 FIFO empty (FLAGA)
51    wire FX2_CE_pre = ~gpif_ctl[1]; //EP4 FX2 FIFO empty (FLAGB)
52    wire FX2_DF_pre = ~gpif_ctl[2]; //EP6 FX2 FIFO full  (FLAGC)
53    wire FX2_CF_pre = ~gpif_ctl[3]; //EP8 FX2 FIFO full  (FLAGD)
54
55    reg FX2_DE, FX2_CE, FX2_DF, FX2_CF;
56    always @(posedge gpif_clk) begin
57        FX2_DE <= FX2_DE_pre; //EP2 FX2 FIFO empty (FLAGA)
58        FX2_CE <= FX2_CE_pre; //EP4 FX2 FIFO empty (FLAGB)
59        FX2_DF <= FX2_DF_pre; //EP6 FX2 FIFO full  (FLAGC)
60        FX2_CF <= FX2_CF_pre; //EP8 FX2 FIFO full  (FLAGD)
61    end
62
63   wire [15:0] gpif_d_out_ctrl, gpif_d_out_data;
64   reg [15:0] gpif_d_out, gpif_d_in;
65
66   // ////////////////////////////////////////////////////////////////////
67   // GPIF bus master state machine
68
69    wire rx_valid, resp_valid;
70    reg tx_valid, ctrl_valid;
71    wire tx_ready, ctrl_ready;
72    reg rx_enable, resp_enable;
73    wire rx_data_enough_occ;
74
75   reg [9:0] transfer_count; //number of lines (a line is 16 bits) in active transfer
76
77   reg [3:0] state; //state machine current state
78   localparam STATE_IDLE    = 0;
79   localparam STATE_THINK   = 1;
80   localparam STATE_DATA_RX = 2;
81   localparam STATE_DATA_TX = 3;
82   localparam STATE_CTRL_RX = 4;
83   localparam STATE_CTRL_TX = 5;
84   localparam STATE_DATA_TX_SLOE = 6;
85   localparam STATE_CTRL_TX_SLOE = 7;
86   localparam STATE_DATA_RX_ADR = 8;
87   localparam STATE_CTRL_RX_ADR = 9;
88
89   //logs the last bus user for xfer fairness
90   //we only care about data rx vs. tx since ctrl pkts are so short
91   reg last_data_bus_hog;
92   localparam BUS_HOG_RX = 0;
93   localparam BUS_HOG_TX = 1;
94
95    wire resp_eof;
96    reg [1:0] idle_count;
97
98   // //////////////////////////////////////////////////////////////
99   // FX2 slave FIFO bus master state machine
100   //
101    always @(posedge gpif_clk)
102    if(gpif_rst) begin
103        state <= STATE_IDLE;
104        sloe <= 1;
105        slrd <= 1;
106        slwr <= 1;
107        pktend <= 1;
108        rx_enable <= 0;
109        tx_valid <= 0;
110        ctrl_valid <= 0;
111        resp_enable <= 0;
112        idle_count <= 0;
113    end
114    else case (state)
115    STATE_IDLE: begin
116        transfer_count <= 0;
117        sloe <= 1;
118        slrd <= 1;
119        slwr <= 1;
120        pktend <= 1;
121        rx_enable <= 0;
122        tx_valid <= 0;
123        ctrl_valid <= 0;
124        resp_enable <= 0;
125        if (idle_count == 2'b11) state <= STATE_THINK;
126        idle_count <= idle_count + 1;
127    end
128
129    STATE_THINK: begin
130
131        idle_count <= 0;
132
133        //handle transitions to other states
134        if(ctrl_ready & ~FX2_CE) begin //if there's room in the ctrl fifo and the FX2 has ctrl data
135            state <= STATE_CTRL_TX_SLOE;
136            fifoadr <= 2'b01;
137            sloe <= 0;
138        end
139        else if(resp_valid & ~FX2_CF) begin //if the ctrl fifo has data and the FX2 isn't full
140            state <= STATE_CTRL_RX_ADR;
141            fifoadr <= 2'b11;
142        end
143        else if(tx_ready & ~FX2_DE & last_data_bus_hog == BUS_HOG_RX) begin //if there's room in the data fifo and the FX2 has data
144            state <= STATE_DATA_TX_SLOE;
145            last_data_bus_hog <= BUS_HOG_TX;
146            fifoadr <= 2'b00;
147            sloe <= 0;
148        end
149        else if(rx_data_enough_occ & ~FX2_DF & last_data_bus_hog == BUS_HOG_TX) begin //if the data fifo has data and the FX2 isn't full
150            state <= STATE_DATA_RX_ADR;
151            last_data_bus_hog <= BUS_HOG_RX;
152            fifoadr <= 2'b10;
153        end
154        else if(tx_ready & ~FX2_DE) begin
155            state <= STATE_DATA_TX_SLOE;
156            last_data_bus_hog <= BUS_HOG_TX;
157            fifoadr <= 2'b00;
158            sloe <= 0;
159        end
160        else if(rx_data_enough_occ & ~FX2_DF) begin
161            state <= STATE_DATA_RX_ADR;
162            last_data_bus_hog <= BUS_HOG_RX;
163            fifoadr <= 2'b10;
164        end
165    end
166
167    STATE_DATA_TX_SLOE: begin //just to assert SLOE one cycle before SLRD
168        state <= STATE_DATA_TX;
169        slrd <= 0;
170    end
171
172    STATE_CTRL_TX_SLOE: begin
173        state <= STATE_CTRL_TX;
174        slrd <= 0;
175    end
176
177    STATE_DATA_RX_ADR: begin //just to assert FIFOADR one cycle before SLWR
178        state <= STATE_DATA_RX;
179        rx_enable <= 1;
180    end
181
182    STATE_CTRL_RX_ADR: begin
183        state <= STATE_CTRL_RX;
184        resp_enable <= 1;
185    end
186
187    STATE_DATA_RX: begin
188        if (FX2_DF_pre || ~rx_valid || transfer_count == DATA_XFER_COUNT-1) begin
189            state <= STATE_IDLE;
190            rx_enable <= 0;
191        end
192        gpif_d_out <= gpif_d_out_data;
193        slwr <= ~rx_valid;
194        transfer_count <= transfer_count + 1;
195    end
196
197    STATE_DATA_TX: begin
198        if (FX2_DE_pre || transfer_count == DATA_XFER_COUNT-1) begin
199            state <= STATE_IDLE;
200            slrd <= 1;
201        end
202        gpif_d_in <= gpif_d;
203        tx_valid <= 1;
204        transfer_count <= transfer_count + 1;
205    end
206
207    STATE_CTRL_RX: begin
208        if (FX2_CF_pre || ~resp_valid || resp_eof || transfer_count == CTRL_XFER_COUNT-1) begin
209            state <= STATE_IDLE;
210            resp_enable <= 0;
211        end
212        pktend <= ~resp_eof;
213        gpif_d_out <= gpif_d_out_ctrl;
214        slwr <= ~resp_valid;
215        transfer_count <= transfer_count + 1;
216    end
217
218    STATE_CTRL_TX: begin
219        if (FX2_CE_pre || transfer_count == CTRL_XFER_COUNT-1) begin
220            state <= STATE_IDLE;
221            slrd <= 1;
222        end
223        gpif_d_in <= gpif_d;
224        ctrl_valid <= 1;
225        transfer_count <= transfer_count + 1;
226    end
227    endcase
228
229   // GPIF output data lines, tristate
230   assign gpif_d = (sloe)? gpif_d_out[15:0] : 16'bz;
231
232   // ////////////////////////////////////////////////////////////////////
233   // TX Data Path
234
235    gpmc16_to_fifo36 #(.FIFO_SIZE(DATA_TX_FIFO_SIZE), .MIN_SPACE16(DATA_XFER_COUNT)) fifo36_to_gpmc16_tx(
236        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
237        .in_data(gpif_d_in), .ready(tx_ready), .valid(tx_valid),
238        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
239        .out_data(tx_data), .out_src_rdy(tx_src_rdy), .out_dst_rdy(tx_dst_rdy)
240    );
241
242   // ////////////////////////////////////////////
243   // RX Data Path
244
245    fifo36_to_gpmc16 #(.FIFO_SIZE(DATA_RX_FIFO_SIZE), .MIN_OCC16(DATA_XFER_COUNT)) fifo36_to_gpmc16_rx(
246        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
247        .in_data(rx_data), .in_src_rdy(rx_src_rdy), .in_dst_rdy(rx_dst_rdy),
248        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
249        .has_data(rx_data_enough_occ),
250        .out_data(gpif_d_out_data), .valid(rx_valid), .enable(rx_enable)
251    );
252
253   // ////////////////////////////////////////////////////////////////////
254   // CTRL TX Data Path
255
256    gpmc16_to_fifo36 #(.FIFO_SIZE(CTRL_TX_FIFO_SIZE), .MIN_SPACE16(CTRL_XFER_COUNT)) fifo36_to_gpmc16_ctrl(
257        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
258        .in_data(gpif_d_in), .ready(ctrl_ready), .valid(ctrl_valid),
259        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
260        .out_data(ctrl_data), .out_src_rdy(ctrl_src_rdy), .out_dst_rdy(ctrl_dst_rdy)
261    );
262
263   // ////////////////////////////////////////////
264   // CTRL RX Data Path
265
266    fifo36_to_gpmc16 #(.FIFO_SIZE(CTRL_RX_FIFO_SIZE)) fifo36_to_gpmc16_resp(
267        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),
268        .in_data(resp_data), .in_src_rdy(resp_src_rdy), .in_dst_rdy(resp_dst_rdy),
269        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst),
270        .out_data(gpif_d_out_ctrl), .valid(resp_valid), .enable(resp_enable),
271        .eof(resp_eof)
272    );
273
274    assign debug = 0;
275
276endmodule // slave_fifo
277