diff options
Diffstat (limited to 'fpga/usrp2/gpif')
-rw-r--r-- | fpga/usrp2/gpif/Makefile.srcs | 13 | ||||
-rw-r--r-- | fpga/usrp2/gpif/fifo36_to_gpmc16.v | 54 | ||||
-rw-r--r-- | fpga/usrp2/gpif/gpmc16_to_fifo36.v | 64 | ||||
-rw-r--r-- | fpga/usrp2/gpif/packet_reframer.v | 70 | ||||
-rw-r--r-- | fpga/usrp2/gpif/slave_fifo.v | 274 |
5 files changed, 475 insertions, 0 deletions
diff --git a/fpga/usrp2/gpif/Makefile.srcs b/fpga/usrp2/gpif/Makefile.srcs new file mode 100644 index 000000000..7909fb5ff --- /dev/null +++ b/fpga/usrp2/gpif/Makefile.srcs @@ -0,0 +1,13 @@ +# +# Copyright 2010-2012 Ettus Research LLC +# + +################################################## +# SERDES Sources +################################################## +GPIF_SRCS = $(abspath $(addprefix $(BASE_DIR)/../gpif/, \ +packet_reframer.v \ +slave_fifo.v \ +fifo36_to_gpmc16.v \ +gpmc16_to_fifo36.v \ +)) diff --git a/fpga/usrp2/gpif/fifo36_to_gpmc16.v b/fpga/usrp2/gpif/fifo36_to_gpmc16.v new file mode 100644 index 000000000..508cd319c --- /dev/null +++ b/fpga/usrp2/gpif/fifo36_to_gpmc16.v @@ -0,0 +1,54 @@ +// +// Copyright 2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +module fifo36_to_gpmc16 +#( + parameter FIFO_SIZE = 9 +) +( + //input fifo interface + input fifo_clk, input fifo_rst, + input [35:0] in_data, + input in_src_rdy, + output in_dst_rdy, + + //output interface + input gpif_clk, input gpif_rst, + output [15:0] out_data, + output valid, + input enable, + output eof +); + + wire [35:0] data_int; + wire src_rdy_int, dst_rdy_int; + + fifo_2clock_cascade #(.WIDTH(36), .SIZE(FIFO_SIZE)) fifo_2clk + (.wclk(fifo_clk), .datain(in_data), .src_rdy_i(in_src_rdy), .dst_rdy_o(in_dst_rdy), .space(), + .rclk(gpif_clk), .dataout(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int), .occupied(), + .arst(fifo_rst | gpif_rst)); + + wire [18:0] data18_int; + fifo36_to_fifo19 #(.LE(1)) f36_to_f19 + (.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), + .f36_datain(data_int), .f36_src_rdy_i(src_rdy_int), .f36_dst_rdy_o(dst_rdy_int), + .f19_dataout(data18_int), .f19_src_rdy_o(valid), .f19_dst_rdy_i(enable) ); + + assign out_data = data18_int[15:0]; + assign eof = data18_int[17]; + +endmodule //fifo_to_gpmc16 diff --git a/fpga/usrp2/gpif/gpmc16_to_fifo36.v b/fpga/usrp2/gpif/gpmc16_to_fifo36.v new file mode 100644 index 000000000..933891715 --- /dev/null +++ b/fpga/usrp2/gpif/gpmc16_to_fifo36.v @@ -0,0 +1,64 @@ +// +// Copyright 2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +module gpmc16_to_fifo36 +#( + parameter FIFO_SIZE = 9, + + //not ready until minimum xfers of space available + parameter MIN_SPACE16 = 128 +) +( + //input interface + input gpif_clk, input gpif_rst, + input [15:0] in_data, + input valid, + output reg ready, + + //output fifo interface + input fifo_clk, input fifo_rst, + output [35:0] out_data, + output out_src_rdy, + input out_dst_rdy +); + + wire [35:0] data_int; + wire src_rdy_int, dst_rdy_int; + wire [18:0] refr_data; + wire refr_src_rdy, refr_dst_rdy; + + wire [15:0] fifo_space; + + always @(posedge gpif_clk) + ready <= (fifo_space >= MIN_SPACE16/2); + + packet_reframer packet_reframer + (.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), + .data_i(in_data), .src_rdy_i(valid), .dst_rdy_o(), + .data_o(refr_data), .src_rdy_o(refr_src_rdy), .dst_rdy_i(refr_dst_rdy)); + + fifo19_to_fifo36 #(.LE(1)) f19_to_f36 + (.clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), + .f19_datain(refr_data), .f19_src_rdy_i(refr_src_rdy), .f19_dst_rdy_o(refr_dst_rdy), + .f36_dataout(data_int), .f36_src_rdy_o(src_rdy_int), .f36_dst_rdy_i(dst_rdy_int)); + + fifo_2clock_cascade #(.WIDTH(36), .SIZE(FIFO_SIZE)) fifo_2clk + (.wclk(gpif_clk), .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int), .space(fifo_space), + .rclk(fifo_clk), .dataout(out_data), .src_rdy_o(out_src_rdy), .dst_rdy_i(out_dst_rdy), .occupied(), + .arst(fifo_rst | gpif_rst)); + +endmodule //fifo_to_gpmc16 diff --git a/fpga/usrp2/gpif/packet_reframer.v b/fpga/usrp2/gpif/packet_reframer.v new file mode 100644 index 000000000..e0ce9e174 --- /dev/null +++ b/fpga/usrp2/gpif/packet_reframer.v @@ -0,0 +1,70 @@ +// +// Copyright 2011-2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +// Join vita packets longer than one GPIF frame + +module packet_reframer + (input clk, input reset, input clear, + input [15:0] data_i, + input src_rdy_i, + output dst_rdy_o, + output [18:0] data_o, + output src_rdy_o, + input dst_rdy_i, + output reg state, + output eof_out, + output reg [15:0] length); + + //reg state; + //reg [15:0] length; + + localparam RF_IDLE = 0; + localparam RF_PKT = 1; + + always @(posedge clk) + if(reset | clear) + state <= RF_IDLE; + else + if(src_rdy_i & dst_rdy_i) + case(state) + RF_IDLE : + begin + length <= {data_i[14:0],1'b0}; + state <= RF_PKT; + end + RF_PKT : + begin + if(eof_out) state <= RF_IDLE; + length <= length - 1; + end + endcase // case (state) + + assign dst_rdy_o = dst_rdy_i; // this is a little pessimistic but ok + assign src_rdy_o = src_rdy_i; + + wire occ_out = 0; + assign eof_out = (state == RF_PKT) & (length == 2); + wire sof_out = (state == RF_IDLE); + assign data_o = {occ_out, eof_out, sof_out, data_i[15:0]}; + + +endmodule // packet_reframer + + + + diff --git a/fpga/usrp2/gpif/slave_fifo.v b/fpga/usrp2/gpif/slave_fifo.v new file mode 100644 index 000000000..0f301f8a6 --- /dev/null +++ b/fpga/usrp2/gpif/slave_fifo.v @@ -0,0 +1,274 @@ +// +// Copyright 2011-2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +////////////////////////////////////////////////////////////////////////////////// + +//this is a FIFO master interface for the FX2 in "slave fifo" mode. + +module slave_fifo + #( + //how many cycles max in a transfer state + parameter DATA_XFER_COUNT = 256, + parameter CTRL_XFER_COUNT = 32, + + //sizes for fifo36 2 clock cascade fifos + parameter DATA_RX_FIFO_SIZE = 9, + parameter DATA_TX_FIFO_SIZE = 9, + parameter CTRL_RX_FIFO_SIZE = 9, + parameter CTRL_TX_FIFO_SIZE = 9 + ) + (// GPIF signals + input gpif_clk, input gpif_rst, + inout [15:0] gpif_d, + input [3:0] gpif_ctl, + output reg sloe, output reg slrd, output reg slwr, output reg pktend, output reg [1:0] fifoadr, + + // FIFO interface + input fifo_clk, input fifo_rst, + output [35:0] tx_data, output tx_src_rdy, input tx_dst_rdy, + input [35:0] rx_data, input rx_src_rdy, output rx_dst_rdy, + output [35:0] ctrl_data, output ctrl_src_rdy, input ctrl_dst_rdy, + input [35:0] resp_data, input resp_src_rdy, output resp_dst_rdy, + + output [31:0] debug + ); + + wire FX2_DE_pre = ~gpif_ctl[0]; //EP2 FX2 FIFO empty (FLAGA) + wire FX2_CE_pre = ~gpif_ctl[1]; //EP4 FX2 FIFO empty (FLAGB) + wire FX2_DF_pre = ~gpif_ctl[2]; //EP6 FX2 FIFO full (FLAGC) + wire FX2_CF_pre = ~gpif_ctl[3]; //EP8 FX2 FIFO full (FLAGD) + + reg FX2_DE, FX2_CE, FX2_DF, FX2_CF; + always @(posedge gpif_clk) begin + FX2_DE <= FX2_DE_pre; //EP2 FX2 FIFO empty (FLAGA) + FX2_CE <= FX2_CE_pre; //EP4 FX2 FIFO empty (FLAGB) + FX2_DF <= FX2_DF_pre; //EP6 FX2 FIFO full (FLAGC) + FX2_CF <= FX2_CF_pre; //EP8 FX2 FIFO full (FLAGD) + end + + wire [15:0] gpif_d_out_ctrl, gpif_d_out_data; + reg [15:0] gpif_d_out, gpif_d_in; + + // //////////////////////////////////////////////////////////////////// + // GPIF bus master state machine + + wire rx_valid, resp_valid; + reg tx_valid, ctrl_valid; + wire tx_ready, ctrl_ready; + reg rx_enable, resp_enable; + + reg [9:0] transfer_count; //number of lines (a line is 16 bits) in active transfer + + reg [3:0] state; //state machine current state + localparam STATE_IDLE = 0; + localparam STATE_THINK = 1; + localparam STATE_DATA_RX = 2; + localparam STATE_DATA_TX = 3; + localparam STATE_CTRL_RX = 4; + localparam STATE_CTRL_TX = 5; + localparam STATE_DATA_TX_SLOE = 6; + localparam STATE_CTRL_TX_SLOE = 7; + localparam STATE_DATA_RX_ADR = 8; + localparam STATE_CTRL_RX_ADR = 9; + + //logs the last bus user for xfer fairness + //we only care about data rx vs. tx since ctrl pkts are so short + reg last_data_bus_hog; + localparam BUS_HOG_RX = 0; + localparam BUS_HOG_TX = 1; + + wire resp_eof; + reg [1:0] idle_count; + + // ////////////////////////////////////////////////////////////// + // FX2 slave FIFO bus master state machine + // + always @(posedge gpif_clk) + if(gpif_rst) begin + state <= STATE_IDLE; + sloe <= 1; + slrd <= 1; + slwr <= 1; + pktend <= 1; + rx_enable <= 0; + tx_valid <= 0; + ctrl_valid <= 0; + resp_enable <= 0; + idle_count <= 0; + end + else case (state) + STATE_IDLE: begin + transfer_count <= 0; + sloe <= 1; + slrd <= 1; + slwr <= 1; + pktend <= 1; + rx_enable <= 0; + tx_valid <= 0; + ctrl_valid <= 0; + resp_enable <= 0; + if (idle_count == 2'b11) state <= STATE_THINK; + idle_count <= idle_count + 1; + end + + STATE_THINK: begin + + idle_count <= 0; + + //handle transitions to other states + if(ctrl_ready & ~FX2_CE) begin //if there's room in the ctrl fifo and the FX2 has ctrl data + state <= STATE_CTRL_TX_SLOE; + fifoadr <= 2'b01; + sloe <= 0; + end + else if(resp_valid & ~FX2_CF) begin //if the ctrl fifo has data and the FX2 isn't full + state <= STATE_CTRL_RX_ADR; + fifoadr <= 2'b11; + end + 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 + state <= STATE_DATA_TX_SLOE; + last_data_bus_hog <= BUS_HOG_TX; + fifoadr <= 2'b00; + sloe <= 0; + end + else if(rx_valid & ~FX2_DF & last_data_bus_hog == BUS_HOG_TX) begin //if the data fifo has data and the FX2 isn't full + state <= STATE_DATA_RX_ADR; + last_data_bus_hog <= BUS_HOG_RX; + fifoadr <= 2'b10; + end + else if(tx_ready & ~FX2_DE) begin + state <= STATE_DATA_TX_SLOE; + last_data_bus_hog <= BUS_HOG_TX; + fifoadr <= 2'b00; + sloe <= 0; + end + else if(rx_valid & ~FX2_DF) begin + state <= STATE_DATA_RX_ADR; + last_data_bus_hog <= BUS_HOG_RX; + fifoadr <= 2'b10; + end + end + + STATE_DATA_TX_SLOE: begin //just to assert SLOE one cycle before SLRD + state <= STATE_DATA_TX; + slrd <= 0; + end + + STATE_CTRL_TX_SLOE: begin + state <= STATE_CTRL_TX; + slrd <= 0; + end + + STATE_DATA_RX_ADR: begin //just to assert FIFOADR one cycle before SLWR + state <= STATE_DATA_RX; + rx_enable <= 1; + end + + STATE_CTRL_RX_ADR: begin + state <= STATE_CTRL_RX; + resp_enable <= 1; + end + + STATE_DATA_RX: begin + if (FX2_DF_pre || ~rx_valid || transfer_count == DATA_XFER_COUNT-1) begin + state <= STATE_IDLE; + rx_enable <= 0; + end + gpif_d_out <= gpif_d_out_data; + slwr <= ~rx_valid; + transfer_count <= transfer_count + 1; + end + + STATE_DATA_TX: begin + if (FX2_DE_pre || transfer_count == DATA_XFER_COUNT-1) begin + state <= STATE_IDLE; + slrd <= 1; + end + gpif_d_in <= gpif_d; + tx_valid <= 1; + transfer_count <= transfer_count + 1; + end + + STATE_CTRL_RX: begin + if (FX2_CF_pre || ~resp_valid || resp_eof || transfer_count == CTRL_XFER_COUNT-1) begin + state <= STATE_IDLE; + resp_enable <= 0; + end + pktend <= ~resp_eof; + gpif_d_out <= gpif_d_out_ctrl; + slwr <= ~resp_valid; + transfer_count <= transfer_count + 1; + end + + STATE_CTRL_TX: begin + if (FX2_CE_pre || transfer_count == CTRL_XFER_COUNT-1) begin + state <= STATE_IDLE; + slrd <= 1; + end + gpif_d_in <= gpif_d; + ctrl_valid <= 1; + transfer_count <= transfer_count + 1; + end + endcase + + // GPIF output data lines, tristate + assign gpif_d = (sloe)? gpif_d_out[15:0] : 16'bz; + + // //////////////////////////////////////////////////////////////////// + // TX Data Path + + gpmc16_to_fifo36 #(.FIFO_SIZE(DATA_TX_FIFO_SIZE), .MIN_SPACE16(DATA_XFER_COUNT)) fifo36_to_gpmc16_tx( + .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), + .in_data(gpif_d_in), .ready(tx_ready), .valid(tx_valid), + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .out_data(tx_data), .out_src_rdy(tx_src_rdy), .out_dst_rdy(tx_dst_rdy) + ); + + // //////////////////////////////////////////// + // RX Data Path + + fifo36_to_gpmc16 #(.FIFO_SIZE(DATA_RX_FIFO_SIZE)) fifo36_to_gpmc16_rx( + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .in_data(rx_data), .in_src_rdy(rx_src_rdy), .in_dst_rdy(rx_dst_rdy), + .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), + .out_data(gpif_d_out_data), .valid(rx_valid), .enable(rx_enable) + ); + + // //////////////////////////////////////////////////////////////////// + // CTRL TX Data Path + + gpmc16_to_fifo36 #(.FIFO_SIZE(CTRL_TX_FIFO_SIZE), .MIN_SPACE16(CTRL_XFER_COUNT)) fifo36_to_gpmc16_ctrl( + .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), + .in_data(gpif_d_in), .ready(ctrl_ready), .valid(ctrl_valid), + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .out_data(ctrl_data), .out_src_rdy(ctrl_src_rdy), .out_dst_rdy(ctrl_dst_rdy) + ); + + // //////////////////////////////////////////// + // CTRL RX Data Path + + fifo36_to_gpmc16 #(.FIFO_SIZE(CTRL_RX_FIFO_SIZE)) fifo36_to_gpmc16_resp( + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .in_data(resp_data), .in_src_rdy(resp_src_rdy), .in_dst_rdy(resp_dst_rdy), + .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), + .out_data(gpif_d_out_ctrl), .valid(resp_valid), .enable(resp_enable), + .eof(resp_eof) + ); + + assign debug = 0; + +endmodule // slave_fifo |