Imported Upstream version 3.2.2
[debian/gnuradio] / usrp / fpga / sdr_lib / tx_buffer.v
1 // -*- verilog -*-
2 //
3 //  USRP - Universal Software Radio Peripheral
4 //
5 //  Copyright (C) 2003 Matt Ettus
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 2 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
20 //
21
22 // Interface to Cypress FX2 bus
23 // A packet is 512 Bytes.  Each fifo line is 2 bytes
24 // Fifo has 1024 or 2048 lines
25
26 module tx_buffer
27   ( // USB Side
28     input usbclk,
29     input bus_reset,  // Used here for the 257-Hack to fix the FX2 bug
30     input [15:0] usbdata,
31     input wire WR,
32     output reg have_space,
33     output reg tx_underrun,
34     input clear_status,
35
36     // DSP Side
37     input txclk,
38     input reset,  // standard DSP-side reset
39     input wire [3:0] channels,
40     output reg [15:0] tx_i_0,
41     output reg [15:0] tx_q_0,
42     output reg [15:0] tx_i_1,
43     output reg [15:0] tx_q_1,
44     input txstrobe,
45     output wire tx_empty,
46     output [31:0] debugbus
47     );
48    
49    wire [11:0]    txfifolevel;
50    wire [15:0]    fifodata;
51    wire           rdreq;
52    reg [3:0]      phase;
53    wire           sop_f, iq_f;
54    reg            sop;
55    
56    // USB Side of FIFO
57    reg [15:0]     usbdata_reg;
58    reg            wr_reg;
59    reg [8:0]      write_count;
60    
61    always @(posedge usbclk)
62      have_space <= (txfifolevel < (4092-256));  // be extra conservative
63    
64    always @(posedge usbclk)
65      begin
66         wr_reg <= WR;
67         usbdata_reg <= usbdata;
68      end
69    
70    always @(posedge usbclk)
71      if(bus_reset)
72        write_count <= 0;
73      else if(wr_reg)
74        write_count <= write_count + 1;
75      else
76        write_count <= 0;
77    
78    always @(posedge usbclk)
79      sop <= WR & ~wr_reg; // Edge detect
80    
81    // FIFO
82    fifo_4k_18 txfifo 
83      ( // USB Write Side
84        .data ( {sop,write_count[0],usbdata_reg} ),
85        .wrreq ( wr_reg & ~write_count[8] ),
86        .wrclk ( usbclk ),
87        .wrfull ( ),
88        .wrempty ( ),
89        .wrusedw ( txfifolevel ),
90        // DSP Read Side
91        .q ( {sop_f, iq_f, fifodata} ),                  
92        .rdreq ( rdreq ),
93        .rdclk ( txclk ),
94        .rdfull ( ),
95        .rdempty ( tx_empty ),
96        .rdusedw (  ),
97        // Async, shared
98        .aclr ( reset ) );
99    
100    // DAC Side of FIFO
101    always @(posedge txclk)
102      if(reset)
103        begin
104           {tx_i_0,tx_q_0,tx_i_1,tx_q_1} <= 64'h0;
105           phase <= 4'd0;
106        end
107      else if(phase == channels)
108        begin
109           if(txstrobe)
110             phase <= 4'd0;
111        end
112      else
113        if(~tx_empty)
114          begin
115             case(phase)
116               4'd0 : tx_i_0 <= fifodata;
117               4'd1 : tx_q_0 <= fifodata;
118               4'd2 : tx_i_1 <= fifodata;
119               4'd3 : tx_q_1 <= fifodata;
120             endcase // case(phase)
121             phase <= phase + 4'd1;
122          end
123       
124    assign    rdreq = ((phase != channels) & ~tx_empty);
125    
126    // Detect Underruns, cross clock domains
127    reg clear_status_dsp, tx_underrun_dsp;
128    always @(posedge txclk)
129      clear_status_dsp <= clear_status;
130
131    always @(posedge usbclk)
132      tx_underrun <= tx_underrun_dsp;
133             
134    always @(posedge txclk)
135      if(reset)
136        tx_underrun_dsp <= 1'b0;
137      else if(txstrobe & (phase != channels))
138        tx_underrun_dsp <= 1'b1;
139      else if(clear_status_dsp)
140        tx_underrun_dsp <= 1'b0;
141
142    // TX debug bus
143    // 
144    // 15:0  txclk  domain => TXA [15:0]
145    // 31:16 usbclk domain => RXA [15:0]
146    
147    assign debugbus[0]     = reset;
148    assign debugbus[1]     = txstrobe;
149    assign debugbus[2]     = rdreq;
150    assign debugbus[6:3]   = phase;
151    assign debugbus[7]     = tx_empty;
152    assign debugbus[8]     = tx_underrun_dsp;
153    assign debugbus[9]     = iq_f;
154    assign debugbus[10]    = sop_f;
155    assign debugbus[14:11] = 0;
156    assign debugbus[15]    = txclk;
157           
158    assign debugbus[16]    = bus_reset;
159    assign debugbus[17]    = WR;
160    assign debugbus[18]    = wr_reg;
161    assign debugbus[19]    = have_space;
162    assign debugbus[20]    = write_count[8];
163    assign debugbus[21]    = write_count[0];
164    assign debugbus[22]    = sop;
165    assign debugbus[23]    = tx_underrun;
166    assign debugbus[30:24] = 0;
167    assign debugbus[31]    = usbclk;
168           
169 endmodule // tx_buffer
170