// -*- verilog -*- // // USRP - Universal Software Radio Peripheral // // Copyright (C) 2003 Matt Ettus // // 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 2 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, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA // // Interface to Cypress FX2 bus // A packet is 512 Bytes. Each fifo line is 2 bytes // Fifo has 1024 or 2048 lines module tx_buffer ( // USB Side input usbclk, input bus_reset, // Used here for the 257-Hack to fix the FX2 bug input [15:0] usbdata, input wire WR, output reg have_space, output reg tx_underrun, input clear_status, // DSP Side input txclk, input reset, // standard DSP-side reset input wire [3:0] channels, output reg [15:0] tx_i_0, output reg [15:0] tx_q_0, output reg [15:0] tx_i_1, output reg [15:0] tx_q_1, input txstrobe, output wire tx_empty, output [31:0] debugbus ); wire [11:0] txfifolevel; wire [15:0] fifodata; wire rdreq; reg [3:0] phase; wire sop_f, iq_f; reg sop; // USB Side of FIFO reg [15:0] usbdata_reg; reg wr_reg; reg [8:0] write_count; always @(posedge usbclk) have_space <= (txfifolevel < (4092-256)); // be extra conservative always @(posedge usbclk) begin wr_reg <= WR; usbdata_reg <= usbdata; end always @(posedge usbclk) if(bus_reset) write_count <= 0; else if(wr_reg) write_count <= write_count + 1; else write_count <= 0; always @(posedge usbclk) sop <= WR & ~wr_reg; // Edge detect // FIFO fifo_4k_18 txfifo ( // USB Write Side .data ( {sop,write_count[0],usbdata_reg} ), .wrreq ( wr_reg & ~write_count[8] ), .wrclk ( usbclk ), .wrfull ( ), .wrempty ( ), .wrusedw ( txfifolevel ), // DSP Read Side .q ( {sop_f, iq_f, fifodata} ), .rdreq ( rdreq ), .rdclk ( txclk ), .rdfull ( ), .rdempty ( tx_empty ), .rdusedw ( ), // Async, shared .aclr ( reset ) ); // DAC Side of FIFO always @(posedge txclk) if(reset) begin {tx_i_0,tx_q_0,tx_i_1,tx_q_1} <= 64'h0; phase <= 4'd0; end else if(phase == channels) begin if(txstrobe) phase <= 4'd0; end else if(~tx_empty) begin case(phase) 4'd0 : tx_i_0 <= fifodata; 4'd1 : tx_q_0 <= fifodata; 4'd2 : tx_i_1 <= fifodata; 4'd3 : tx_q_1 <= fifodata; endcase // case(phase) phase <= phase + 4'd1; end assign rdreq = ((phase != channels) & ~tx_empty); // Detect Underruns, cross clock domains reg clear_status_dsp, tx_underrun_dsp; always @(posedge txclk) clear_status_dsp <= clear_status; always @(posedge usbclk) tx_underrun <= tx_underrun_dsp; always @(posedge txclk) if(reset) tx_underrun_dsp <= 1'b0; else if(txstrobe & (phase != channels)) tx_underrun_dsp <= 1'b1; else if(clear_status_dsp) tx_underrun_dsp <= 1'b0; // TX debug bus // // 15:0 txclk domain => TXA [15:0] // 31:16 usbclk domain => RXA [15:0] assign debugbus[0] = reset; assign debugbus[1] = txstrobe; assign debugbus[2] = rdreq; assign debugbus[6:3] = phase; assign debugbus[7] = tx_empty; assign debugbus[8] = tx_underrun_dsp; assign debugbus[9] = iq_f; assign debugbus[10] = sop_f; assign debugbus[14:11] = 0; assign debugbus[15] = txclk; assign debugbus[16] = bus_reset; assign debugbus[17] = WR; assign debugbus[18] = wr_reg; assign debugbus[19] = have_space; assign debugbus[20] = write_count[8]; assign debugbus[21] = write_count[0]; assign debugbus[22] = sop; assign debugbus[23] = tx_underrun; assign debugbus[30:24] = 0; assign debugbus[31] = usbclk; endmodule // tx_buffer