diff options
Diffstat (limited to 'fpga/usrp1/sdr_lib/tx_buffer.v')
-rw-r--r-- | fpga/usrp1/sdr_lib/tx_buffer.v | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/fpga/usrp1/sdr_lib/tx_buffer.v b/fpga/usrp1/sdr_lib/tx_buffer.v new file mode 100644 index 000000000..58642229d --- /dev/null +++ b/fpga/usrp1/sdr_lib/tx_buffer.v @@ -0,0 +1,170 @@ +// -*- 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 + |