diff options
Diffstat (limited to 'fpga/usrp3/lib/gpif2')
| -rw-r--r-- | fpga/usrp3/lib/gpif2/Makefile.srcs | 13 | ||||
| -rw-r--r-- | fpga/usrp3/lib/gpif2/fifo64_to_gpif2.v | 64 | ||||
| -rw-r--r-- | fpga/usrp3/lib/gpif2/gpif2_error_checker.v | 126 | ||||
| -rw-r--r-- | fpga/usrp3/lib/gpif2/gpif2_slave_fifo32.v | 375 | ||||
| -rw-r--r-- | fpga/usrp3/lib/gpif2/gpif2_to_fifo64.v | 118 | 
5 files changed, 696 insertions, 0 deletions
| diff --git a/fpga/usrp3/lib/gpif2/Makefile.srcs b/fpga/usrp3/lib/gpif2/Makefile.srcs new file mode 100644 index 000000000..1624643f6 --- /dev/null +++ b/fpga/usrp3/lib/gpif2/Makefile.srcs @@ -0,0 +1,13 @@ +# +# Copyright 2010-2013 Ettus Research LLC +# + +################################################## +# SERDES Sources +################################################## +GPIF2_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/gpif2/, \ +gpif2_slave_fifo32.v \ +gpif2_to_fifo64.v \ +fifo64_to_gpif2.v \ +gpif2_error_checker.v \ +)) diff --git a/fpga/usrp3/lib/gpif2/fifo64_to_gpif2.v b/fpga/usrp3/lib/gpif2/fifo64_to_gpif2.v new file mode 100644 index 000000000..cf3a221b7 --- /dev/null +++ b/fpga/usrp3/lib/gpif2/fifo64_to_gpif2.v @@ -0,0 +1,64 @@ +// +// Copyright 2012-2013 Ettus Research LLC +// + + +module fifo64_to_gpif2 +#( +    parameter FIFO_SIZE = 9 +) +( +    //input fifo interface +    input fifo_clk, input fifo_rst, +    input [63:0] i_tdata, +    input i_tlast, +    input i_tvalid, +    output i_tready, + +    //output interface +    input gpif_clk, input gpif_rst, +    output [31:0] o_tdata, +    output o_tlast, +    output o_tvalid, +    input o_tready +); + +    wire [31:0] i32_tdata; +    wire i32_tlast; +    wire i32_tvalid, i32_tready; + +    axi_fifo64_to_fifo32 fifo64_to_fifo32 +    ( +        .clk(fifo_clk), .reset(fifo_rst), .clear(1'b0), +        .i_tdata(i_tdata), .i_tuser(3'b0/*done care*/), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready), +        .o_tdata(i32_tdata), .o_tuser(/*ignored cuz vita has len*/), .o_tlast(i32_tlast), .o_tvalid(i32_tvalid), .o_tready(i32_tready) +    ); + +    wire [31:0] gate_tdata; +    wire gate_tlast; +    wire gate_tvalid, gate_tready; + +    axi_fifo_2clk #(.WIDTH(33), .SIZE(0/*SRL*/)) cross_clock_fifo +    ( +        .reset(fifo_rst | gpif_rst), +        .i_aclk(fifo_clk), .i_tdata({i32_tlast, i32_tdata}), .i_tvalid(i32_tvalid), .i_tready(i32_tready), +        .o_aclk(gpif_clk), .o_tdata({gate_tlast, gate_tdata}), .o_tvalid(gate_tvalid), .o_tready(gate_tready) +    ); + +    wire [31:0] int0_tdata; wire int0_tlast, int0_tvalid, int0_tready; + +    axi_packet_gate #(.WIDTH(32), .SIZE(FIFO_SIZE)) buffer_whole_pkt +    ( +        .clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), +        .i_tdata(gate_tdata), .i_tlast(gate_tlast), .i_terror(1'b0), .i_tvalid(gate_tvalid), .i_tready(gate_tready), +        .o_tdata(int0_tdata), .o_tlast(int0_tlast), .o_tvalid(int0_tvalid), .o_tready(int0_tready) +    ); + +    axi_fifo #(.WIDTH(33), .SIZE(0)) outgress_timing_fifo +    ( +        .clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), +        .i_tdata({int0_tlast, int0_tdata}), .i_tvalid(int0_tvalid), .i_tready(int0_tready), .space(), +        .o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), .occupied() +    ); + +endmodule //fifo_to_gpmc16 diff --git a/fpga/usrp3/lib/gpif2/gpif2_error_checker.v b/fpga/usrp3/lib/gpif2/gpif2_error_checker.v new file mode 100644 index 000000000..0ec21a758 --- /dev/null +++ b/fpga/usrp3/lib/gpif2/gpif2_error_checker.v @@ -0,0 +1,126 @@ + +// Copyright 2013 Ettus Research LLC + +// inspect the input for invalid conditions +// when bad - drain input, flag error, and insert error msg packet +// +// Packets alignment errors are searched for in two different ways: +// 1) Blatently illegal values in what is assumed to be the PACKET_LENGTH field +// in the CHDR header +// (We could probably improve this by looking at other fields of the header that  +// have a limited range of values) +// 2) Packet length indicating an EOF word that doesn't have TLAST set in the FIFO. +// (Upstream can howvever legally insert TLAST in the FIFO for words that are not EOF) +//  +// Packet allignment recovery strategy is to wait for TLAST asserted and then decode the  +// following data assuming it is the start of new CHDR headers. +// +//TODO - insert bad packet + +module gpif2_error_checker +  #(parameter SIZE = 9) +  (input clk, input reset, input clear, +   input [31:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, +   output [31:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, +   output bus_error, output [63:0] debug); + +    wire [31:0] gate_tdata; +    wire gate_tlast, gate_terror; +    wire gate_tvalid, gate_tready; + +    localparam STATE_HDR = 0; +    localparam STATE_FWD = 1; +    localparam STATE_EOF = 2; +    localparam STATE_WAIT = 3; +    reg [1:0] state; + +    reg [15:0] lines32; +    reg [11:0] seq_id_ref; +    reg        seq_id_bad; +    reg        seq_id_wayoff; +    + +    wire [15:0] hdr_bytes = i_tdata[15:0] + 3; //round up to multiple of 4 +    wire [15:0] hdr_lines32 = {2'b0, hdr_bytes[15:2]}; //convert to lines32 count +    wire [11:0] seq_id_actual = i_tdata[27:16]; +    +    +    wire obviously_bad_hdr = (hdr_lines32 == 16'h0) || (hdr_lines32 > (1 << SIZE)); + +    always @(posedge clk) begin +        if (reset | clear) begin +            state <= STATE_HDR; +            lines32 <= 16'b0; +	    seq_id_ref <= 12'h0; +	    seq_id_bad <= 0; +	    seq_id_wayoff <= 0; +	    +	    +        end +        else case (state) + +        STATE_HDR: begin //forward header and grab vita length +            if (i_tvalid && i_tready) begin +                if (obviously_bad_hdr)           state <= STATE_WAIT; +                else if (hdr_lines32 == 16'h1)  state <= STATE_HDR; +                else if (hdr_lines32 == 16'h2)  state <= STATE_EOF; +                else                            state <= STATE_FWD; +	        seq_id_bad <= (seq_id_actual != seq_id_ref); +	        seq_id_wayoff <= (seq_id_actual != seq_id_ref) | +				(seq_id_actual != seq_id_ref+1) | +				(seq_id_actual != seq_id_ref+2) | +				(seq_id_actual != seq_id_ref+3); +	        if (seq_id_actual != seq_id_ref) +		 seq_id_ref <= seq_id_actual + 1; +	        else +		 seq_id_ref <= seq_id_ref + 1; +            end +            lines32 <= hdr_lines32; +	     +        end + +        STATE_FWD: begin //forward the rest of vita packet +            if (i_tvalid && i_tready) begin +                if (lines32 == 16'h3) state <= STATE_EOF; +                lines32 <= lines32 - 1'b1; +            end +        end + +        STATE_EOF: begin //do last line of vita frame + eof +	   if (i_tvalid && i_tready)  +	     if (gate_tlast) state <= STATE_HDR; +	     else state <= STATE_WAIT; // Try somehow to get synchronized again. +        end + +        STATE_WAIT: begin //drop until idle +            if (i_tvalid && i_tready && i_tlast) state <= STATE_HDR; +        end + +        endcase //state +    end + +    assign bus_error = (gate_terror && gate_tvalid && gate_tready) || ((state == STATE_HDR) && i_tvalid && i_tready && obviously_bad_hdr); +    assign gate_tlast = (state == STATE_HDR)? (hdr_lines32 == 16'h1) : (state == STATE_EOF); +    assign gate_tdata = i_tdata; +    assign gate_tvalid = i_tvalid && ((state == STATE_HDR)? !obviously_bad_hdr : (state != STATE_WAIT)); +    assign i_tready = gate_tready; + +    axi_packet_gate #(.WIDTH(32), .SIZE(SIZE)) gate_xfer +    ( +        .clk(clk), .reset(reset), .clear(clear), +        .i_tdata(gate_tdata), .i_tlast(gate_tlast), .i_terror(1'b0), .i_tvalid(gate_tvalid), .i_tready(gate_tready), +        .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready) +    ); +   assign  debug = {13'b0, +		    seq_id_wayoff, //[50]      [114] +		    gate_terror,  // [49]      [113] +		    obviously_bad_hdr, // [48] [112] +		    seq_id_bad,   // [47]      [111] +		    seq_id_ref,   // [46:35]   [110:99] +		    i_tlast,      // [34]      [98] +		    i_tready,     // [33]      [97] +		    i_tvalid,     // [32]      [96] +		    i_tdata};     // [31:0]    [95:64] +    + +endmodule // cvita_insert_tlast diff --git a/fpga/usrp3/lib/gpif2/gpif2_slave_fifo32.v b/fpga/usrp3/lib/gpif2/gpif2_slave_fifo32.v new file mode 100644 index 000000000..f332a6ab3 --- /dev/null +++ b/fpga/usrp3/lib/gpif2/gpif2_slave_fifo32.v @@ -0,0 +1,375 @@ +// +// Copyright 2011-2013 Ettus Research LLC +// + + +////////////////////////////////////////////////////////////////////////////////// + +//this is a FIFO master interface for the FX3 in "slave fifo" mode. + +module gpif2_slave_fifo32 +#( +    //sizes for fifo64 2 clock cascade fifos +    parameter DATA_RX_FIFO_SIZE = 12, //max vita pkt size +    parameter DATA_TX_FIFO_SIZE = 12, //max vita pkt size +    parameter CTRL_RX_FIFO_SIZE = 5,  //small resp packets +    parameter CTRL_TX_FIFO_SIZE = 5, //small ctrl packets + +    //address constants for the endpoints +    parameter ADDR_DATA_TX = 2'b00, +    parameter ADDR_DATA_RX = 2'b01, +    parameter ADDR_CTRL_TX = 2'b10, +    parameter ADDR_CTRL_RX = 2'b11, + +    parameter END_WITH_COMMA = 0 +) +   (// GPIF signals +    input gpif_clk, input gpif_rst, input gpif_enb, +    inout [31:0] gpif_d, +    input [3:0] gpif_ctl, +    output reg sloe, +    output reg slrd, +    output reg slwr, +    output slcs, +    output reg pktend, +    output reg [1:0] fifoadr, + +    // FIFO interfaces +    input fifo_clk, input fifo_rst, + +    output [63:0] tx_tdata, output tx_tlast, output tx_tvalid, input tx_tready, +    input [63:0] rx_tdata, input rx_tlast, input rx_tvalid, output rx_tready, +    output [63:0] ctrl_tdata, output ctrl_tlast, output ctrl_tvalid, input ctrl_tready, +    input [63:0] resp_tdata, input resp_tlast, input resp_tvalid, output resp_tready, + +    output [31:0] debug +    ); + +   reg 		  fifo_nearly_full; +   wire 	  ctrl_tx_fifo_nearly_full, data_tx_fifo_nearly_full; +   wire 	  ctrl_tx_fifo_has_space, data_tx_fifo_has_space; +    + +   wire [159:0]   debug_tx_data, debug_tx_ctrl; +    +    assign slcs = 1'b0; + +    //DMA FIFO ready and watermark flags +    reg EP_READY, EP_READY1, EP_WMARK, EP_WMARK1; +    always @(posedge gpif_clk) EP_READY <= gpif_ctl[0]; +    always @(posedge gpif_clk) EP_WMARK <= gpif_ctl[1]; +    always @(posedge gpif_clk) EP_READY1 <= EP_READY; +    always @(posedge gpif_clk) EP_WMARK1 <= EP_WMARK; + +    // GPIF output data lines, tristate +    reg [31:0] gpif_data_in, gpif_data_out; +    always @(posedge gpif_clk) gpif_data_in <= gpif_d; +    assign gpif_d = sloe ? gpif_data_out[31:0] : 32'bz; + +   // //////////////////////////////////////////////////////////////////// +   // GPIF bus master state machine + +    wire wr_fifo_xfer, wr_fifo_eof; +    wire [31:0] wr_fifo_data; +    reg read_ready_go, write_ready_go; +    reg wr_one, rd_one; + +    reg [3:0] state; //state machine current state +    localparam STATE_IDLE  = 0; +    localparam STATE_THINK = 1; +    localparam STATE_READ  = 2; +    localparam STATE_WRITE = 3; +    localparam STATE_WAIT = 4; + +    reg [2:0] idle_cycles; +    reg [1:0] last_addr, next_addr; +    wire local_fifo_ready; + +    reg slrd1, slrd2, slrd3; +    +   always @(posedge gpif_clk) +     if (gpif_rst) begin +        slrd1 <= 1; +        slrd2 <= 1; +        slrd3 <= 1; +     end else begin +        slrd1 <= slrd; +        slrd2 <= slrd1; +        slrd3 <= slrd2; +     end +    +   wire RD_VALID = ~slrd3; +   wire RD_LAST = slrd2; +   wire WR_VALID = (EP_WMARK1 || !wr_one); + +   // ////////////////////////////////////////////////////////////// +   // FX2 slave FIFO bus master state machine +   // +    always @(posedge gpif_clk) +    if(gpif_rst) begin +        state <= STATE_IDLE; +        sloe <= 0; +        slrd <= 1; +        slwr <= 1; +        pktend <= 1; +        gpif_data_out <= 32'b0; +        idle_cycles <= 0; +        fifoadr <= 0; +        wr_one <= 1'b0; +        rd_one <= 1'b0; +        last_addr <= 2'b0; +    end +    else if (gpif_enb) begin +        case (state) + +	  // +	  // Increment fifoadr to point at next thread, set all strobes to idle, +	  // +        STATE_IDLE: begin +            sloe <= 0; +            slrd <= 1; +            slwr <= 1; +            pktend <= 1; +            gpif_data_out <= 32'b0; +            fifoadr <= next_addr; +            state <= STATE_WAIT; +            idle_cycles <= 0; +        end + +	  // +	  // now wait here for 8 clock cycles before transitioning to STATE_THINK. +	  // We stay in this state if no local FIFO's can proceed at this point. +	  // +        STATE_WAIT: begin +            if (local_fifo_ready) begin +                idle_cycles <= idle_cycles + 1'b1; +                if (idle_cycles == 3'b111) state <= STATE_THINK; +            end +            else begin +                idle_cycles <= 3'b0; +                fifoadr <= fifoadr + 2'b1; +            end +        end + +	  // +	  // If there is a read to start, assert SLRD and SLOE and transition to STATE_READ. +	  // If there is a write to perform, set flags that says there is the possibility to do at least +	  // one write (wr_one) and transition to STATE_WRITE +	  // +        STATE_THINK: begin + +            if (EP_READY1 && read_ready_go) begin +                state <= STATE_READ; +                slrd <= 0; +                rd_one <= 0; +            end +            else if (EP_READY1 && write_ready_go) begin +                state <= STATE_WRITE; +                sloe <= 1; +                wr_one <= 1'b0; +            end +            else begin +                state <= STATE_IDLE; +            end + +            idle_cycles <= 0; +            last_addr <= fifoadr; +        end + +	  // If flag rd_one is set (armed 5 cycles after slrd goes initialy assrted) and RD_VALID has gone deasserted +	  // (meaning that the watermark deasserted 5 clock cycles ago) transition to STATE_IDLE. +	  // If watermark deasserted 2 cycles ago de-assert slrd ...read data is still traveling in the pipeline. +	  // Whilst RD_VALID stays asserted keep the rd_one flag armed. +        STATE_READ: begin +            if (rd_one && ~RD_VALID) state <= STATE_IDLE; +            if (~EP_WMARK1 | fifo_nearly_full) slrd <= 1; +            if (RD_VALID) rd_one <= 1'b1; +        end + +	  // If local FIFO goes empty or tlast is set then transition to STATE_IDLE +	  // Push local FIFO data out onto GPIF data bus. +	  // if local FIFO has valid data then assert slwr +	  // if local FIFO assertes tlast then assert pktend +	  // If WR_VALID asserted (because wr_one already asserted in the first cycle in this state) +	  // now clear wr_one (watermark will keep WR_VALID asserted from now on if this is a burst). +	  // +        STATE_WRITE: begin +            if (~wr_fifo_xfer || wr_fifo_eof) state <= STATE_IDLE; +            gpif_data_out <= wr_fifo_data; +            slwr <= ~wr_fifo_xfer; +            pktend <= ~wr_fifo_eof; +            if (WR_VALID) wr_one <= 1'b1; +        end + +        default: state <= STATE_IDLE; +        endcase +    end + +   // /////////////////////////////////////////////////////////////////// +   // fifo signal assignments and enables + +    //output from fifos - ready to xfer +    wire data_tx_tready, ctrl_tx_tready; +    wire ctrl_rx_tvalid, data_rx_tvalid; + +    //Priority encoding for the the next address to service: +    //The next address to service is based on the readiness +    //of the internal fifos and last serviced fairness metric. +    always @(posedge gpif_clk) next_addr <= +        ((ctrl_rx_tvalid && last_addr != ADDR_CTRL_RX)? ADDR_CTRL_RX : +        ((ctrl_tx_fifo_has_space && last_addr != ADDR_CTRL_TX)? ADDR_CTRL_TX : +        ((data_rx_tvalid && last_addr != ADDR_DATA_RX)? ADDR_DATA_RX : +        ((data_tx_fifo_has_space && last_addr != ADDR_DATA_TX)? ADDR_DATA_TX : +        (fifoadr + 2'b1) +    )))); + +    //Help the FPGA search to only look for addrs that the FPGA is ready for +    assign local_fifo_ready = +        (ctrl_rx_tvalid && (fifoadr == ADDR_CTRL_RX)) || +        (ctrl_tx_fifo_has_space && (fifoadr == ADDR_CTRL_TX)) || +        (data_rx_tvalid && (fifoadr == ADDR_DATA_RX)) || +        (data_tx_fifo_has_space && (fifoadr == ADDR_DATA_TX)); + +    always @(posedge gpif_clk) fifo_nearly_full <= +        (ctrl_tx_fifo_nearly_full && (fifoadr == ADDR_CTRL_TX)) || +        (data_tx_fifo_nearly_full && (fifoadr == ADDR_DATA_TX)); + +    always @(posedge gpif_clk) read_ready_go <= +        (ctrl_tx_fifo_has_space && (fifoadr == ADDR_CTRL_TX)) || +        (data_tx_fifo_has_space && (fifoadr == ADDR_DATA_TX)); + +    always @(posedge gpif_clk) write_ready_go <= +        (ctrl_rx_tvalid && (fifoadr == ADDR_CTRL_RX)) || +        (data_rx_tvalid && (fifoadr == ADDR_DATA_RX)); + +    //fifo xfer enable +    wire data_rx_tready = (state == STATE_WRITE) && (fifoadr == ADDR_DATA_RX) && WR_VALID; +    wire ctrl_rx_tready = (state == STATE_WRITE) && (fifoadr == ADDR_CTRL_RX) && WR_VALID; +    wire data_tx_tvalid = (state == STATE_READ) && (fifoadr == ADDR_DATA_TX) && RD_VALID; +    wire ctrl_tx_tvalid = (state == STATE_READ) && (fifoadr == ADDR_CTRL_TX) && RD_VALID; + +    //outputs from rx fifo paths +    wire ctrl_rx_tlast, data_rx_tlast; +    wire [31:0] ctrl_rx_tdata, data_rx_tdata; + +    //mux rx outputs for gpif state machine +    assign wr_fifo_xfer = (fifoadr == ADDR_CTRL_RX)? (ctrl_rx_tvalid && ctrl_rx_tready) : (data_rx_tvalid && data_rx_tready); +    assign wr_fifo_eof = wr_fifo_xfer && ((fifoadr == ADDR_CTRL_RX)? ctrl_rx_tlast : data_rx_tlast); +    assign wr_fifo_data = (fifoadr == ADDR_CTRL_RX)? ctrl_rx_tdata : data_rx_tdata; + +    wire ctrl_bus_error, tx_bus_error; + +   // //////////////////////////////////////////////////////////////////// +   // TX Data Path + +    gpif2_to_fifo64 #(.FIFO_SIZE(DATA_TX_FIFO_SIZE)) gpif2_to_fifo64_tx( +        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), +        .i_tdata(gpif_data_in), .i_tlast(RD_LAST), .i_tvalid(data_tx_tvalid), .i_tready(data_tx_tready), +        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),  +        .fifo_nearly_full(data_tx_fifo_nearly_full), .fifo_has_space(data_tx_fifo_has_space), +        .o_tdata(tx_tdata), .o_tlast(tx_tlast), .o_tvalid(tx_tvalid), .o_tready(tx_tready), +        .bus_error(tx_bus_error), .debug(debug_tx_data) +    ); + +   // //////////////////////////////////////////// +   // RX Data Path + +    fifo64_to_gpif2 #(.FIFO_SIZE(DATA_RX_FIFO_SIZE)) fifo64_to_gpif2_rx( +        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), +        .i_tdata(rx_tdata), .i_tlast(rx_tlast), .i_tvalid(rx_tvalid), .i_tready(rx_tready), +        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), +        .o_tdata(data_rx_tdata), .o_tlast(data_rx_tlast), .o_tvalid(data_rx_tvalid), .o_tready(data_rx_tready) +    ); + +   // //////////////////////////////////////////////////////////////////// +   // CTRL path + +    gpif2_to_fifo64 #(.FIFO_SIZE(CTRL_TX_FIFO_SIZE)) gpif2_to_fifo64_ctrl( +        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), +        .i_tdata(gpif_data_in), .i_tlast(RD_LAST), .i_tvalid(ctrl_tx_tvalid), .i_tready(ctrl_tx_tready), +        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst),  +        .fifo_nearly_full(ctrl_tx_fifo_nearly_full), .fifo_has_space(ctrl_tx_fifo_has_space), +        .o_tdata(ctrl_tdata), .o_tlast(ctrl_tlast), .o_tvalid(ctrl_tvalid), .o_tready(ctrl_tready), +        .bus_error(ctrl_bus_error), .debug(debug_tx_ctrl) +    ); + +   // //////////////////////////////////////////////////////////////////// +   // RESP path + +    fifo64_to_gpif2 #(.FIFO_SIZE(CTRL_RX_FIFO_SIZE)) fifo64_to_gpif2_resp( +        .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), +        .i_tdata(resp_tdata), .i_tlast(resp_tlast), .i_tvalid(resp_tvalid), .i_tready(resp_tready), +        .gpif_clk(gpif_clk), .gpif_rst(gpif_rst), +        .o_tdata(ctrl_rx_tdata), .o_tlast(ctrl_rx_tlast), .o_tvalid(ctrl_rx_tvalid), .o_tready(ctrl_rx_tready) +    ); + +   // //////////////////////////////////////////// +   //    DEBUG + +    wire [31:0] debug0 = { +        sloe, slrd, slwr, pktend, fifoadr, EP_READY, EP_WMARK, //8 +        state, //4 +        data_tx_tvalid, data_tx_tready, data_rx_tvalid, data_rx_tready, //4 +        gpif_d[15:0] //16 +    }; + +    reg [31:0] debug_reg0; +    reg [31:0] debug_reg1; +    reg [31:0] debug_reg2; +    always @(posedge gpif_clk) debug_reg0 <= debug0; +    always @(posedge gpif_clk) debug_reg1 <= debug_reg0; +    always @(posedge gpif_clk) debug_reg2 <= debug_reg1; +    assign debug = debug_reg2; + +   wire [37:0] debug_resp = { +			     resp_tlast,        // 37 +			     resp_tready,       // 36 +			     resp_tvalid,       // 35 +			     ctrl_rx_tlast,     // 34 +			     ctrl_rx_tready,    // 33 +			     ctrl_rx_tvalid,    // 32 +			     ctrl_rx_tdata      // 31:0 +			     }; +    +    +    reg [255:0] debug1,debug2; +    +    always @(posedge gpif_clk) debug1 <= {debug_resp,debug_tx_ctrl,debug0}; +   always @(posedge gpif_clk) debug2 <= debug1; +    +    +  +   wire [35:0] CONTROL0,CONTROL1; + /* +   chipscope_ila_32 chipscope_ila_32( +				   .CONTROL(CONTROL0), // INOUT BUS [35:0] +				   .CLK(gpif_clk), // IN +				   .TRIG0(debug2) // IN BUS [31:0] +				   ); +    +   chipscope_ila_128  chipscope_ila_128( +				   .CONTROL(CONTROL1), // INOUT BUS [35:0] +				   .CLK(fifo_clk), // IN +				   .TRIG0({debug4,debug6}) // IN BUS [31:0] +				   ); +    +    +   chipscope_ila_256 chipscope_ila_256( +				     .CONTROL(CONTROL0), // INOUT BUS [35:0] +				     .CLK(gpif_clk), // IN +				     .TRIG0(debug2) // IN BUS [31:0] +				     ); +   +  chipscope_ila_32  chipscope_ila_32_2( +				   .CONTROL(CONTROL1), // INOUT BUS [35:0] +				   .CLK(gpif_clk), // IN +				   .TRIG0(32'd0) // IN BUS [31:0] +				   ); +    +   chipscope_icon  chipscope_icon( +				 .CONTROL0(CONTROL0), // INOUT BUS [35:0] +				   .CONTROL1(CONTROL1) // INOUT BUS [35:0] +				    ); + +   */ +endmodule // gpif2_slave_fifo32 diff --git a/fpga/usrp3/lib/gpif2/gpif2_to_fifo64.v b/fpga/usrp3/lib/gpif2/gpif2_to_fifo64.v new file mode 100644 index 000000000..3d60c7326 --- /dev/null +++ b/fpga/usrp3/lib/gpif2/gpif2_to_fifo64.v @@ -0,0 +1,118 @@ +// +// Copyright 2012-2013 Ettus Research LLC +// + + +module gpif2_to_fifo64 +#( +    parameter FIFO_SIZE = 9 +) +( +    //input interface +    input gpif_clk, input gpif_rst, +    input [31:0] i_tdata, +    input i_tlast, +    input i_tvalid, +    output i_tready, +    output fifo_has_space, +    output fifo_nearly_full, +  +    //output fifo interface +    input fifo_clk, input fifo_rst, +    output [63:0] o_tdata, +    output o_tlast, +    output o_tvalid, +    input o_tready, + +    output bus_error, +    output [159:0] debug +); + +    wire [31:0] int_tdata; +    wire int_tlast; +    wire int_tvalid, int_tready; + +    wire [31:0] int0_tdata; wire int0_tlast, int0_tvalid, int0_tready; + +    //this fifo provides a space signal so we know a burst is possible +    localparam BURST_SIZE = (FIFO_SIZE < 8)? FIFO_SIZE : 8; +    wire [15:0] space; +   +    +    assign fifo_has_space = space >= (1 << BURST_SIZE); +    assign  fifo_nearly_full = (space < 6); // 5 spaces left. +    +    axi_fifo #(.WIDTH(33), .SIZE(0)) ingress_timing_fifo +    ( +        .clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), +        .i_tdata({i_tlast, i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready), .space(), +        .o_tdata({int0_tlast, int0_tdata}), .o_tvalid(int0_tvalid), .o_tready(int0_tready), .occupied() +    ); +    axi_fifo #(.WIDTH(33), .SIZE(BURST_SIZE)) min_read_buff +    ( +        .clk(gpif_clk), .reset(gpif_rst), .clear(1'b0), +        .i_tdata({int0_tlast, int0_tdata}), .i_tvalid(int0_tvalid), .i_tready(int0_tready), .space(space), +        .o_tdata({int_tlast, int_tdata}), .o_tvalid(int_tvalid), .o_tready(int_tready), .occupied() +    ); +   + reg 	   input_write_error; +    +   always @(posedge gpif_clk)  input_write_error <= i_tvalid & ~i_tready; +    + +    wire [31:0] chk_tdata; +    wire chk_tlast; +    wire chk_tvalid, chk_tready; + +    axi_fifo_2clk #(.WIDTH(33), .SIZE(0/*SRL*/)) cross_clock_fifo +    ( +        .reset(fifo_rst | gpif_rst), +        .i_aclk(gpif_clk), .i_tdata({int_tlast, int_tdata}), .i_tvalid(int_tvalid), .i_tready(int_tready), +        .o_aclk(fifo_clk), .o_tdata({chk_tlast, chk_tdata}), .o_tvalid(chk_tvalid), .o_tready(chk_tready) +    ); + +    wire [31:0] o32_tdata; +    wire o32_tlast; +    wire o32_tvalid, o32_tready; + +    //reframes a tlast from the vita header - and drops bad packets +    //* +    gpif2_error_checker #(.SIZE(FIFO_SIZE)) checker +    ( +        .clk(fifo_clk), .reset(fifo_rst), .clear(1'b0), +        .i_tdata(chk_tdata), .i_tlast(chk_tlast), .i_tvalid(chk_tvalid), .i_tready(chk_tready), +        .o_tdata(o32_tdata), .o_tlast(o32_tlast), .o_tvalid(o32_tvalid), .o_tready(o32_tready), +        .bus_error(bus_error), .debug(debug[63:0]) +    ); +    //*/ +    //assign o32_tdata = chk_tdata; +    //assign o32_tlast = chk_tlast; +    //assign o32_tvalid = chk_tvalid; +    //assign chk_tready = o32_tready; + +    axi_fifo32_to_fifo64 fifo32_to_fifo64 +    ( +        .clk(fifo_clk), .reset(fifo_rst), .clear(1'b0), +        .i_tdata(o32_tdata), .i_tuser(2'b0/*always 32 bits*/), .i_tlast(o32_tlast), .i_tvalid(o32_tvalid), .i_tready(o32_tready), +        .o_tdata(o_tdata), .o_tuser(/*ignored cuz vita has len*/), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready) +    ); + +  assign debug[159:64] = { +			  fifo_nearly_full, // 146 +			  space[9:0],      // 145:136 +			  input_write_error, // 135 +			  int_tlast,       // 134 +			  int_tready,      // 133 +			  int_tvalid,      // 132 +			  i_tlast,         // 131 +			  i_tready,    // 130 +			  fifo_has_space,        // 129 +			  i_tvalid,        // 128 +			  int_tdata[31:0], // 127:96 +			  i_tdata[31:0]    // 95:64 +			  }; + +    +    + +endmodule //fifo_to_gpif2 | 
