Imported Upstream version 3.0
[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   ( input usbclk,
28     input bus_reset,  // Used here for the 257-Hack to fix the FX2 bug
29     input reset,  // standard DSP-side reset
30     input [15:0] usbdata,
31     input wire WR,
32     output wire have_space,
33     output reg tx_underrun,
34     input wire [3:0] channels,
35     output reg [15:0] tx_i_0,
36     output reg [15:0] tx_q_0,
37     output reg [15:0] tx_i_1,
38     output reg [15:0] tx_q_1,
39     output reg [15:0] tx_i_2,
40     output reg [15:0] tx_q_2,
41     output reg [15:0] tx_i_3,
42     output reg [15:0] tx_q_3,
43     input txclk,
44     input txstrobe,
45     input clear_status,
46     output wire tx_empty,
47     output [11:0] debugbus
48     );
49    
50    wire [11:0] txfifolevel;
51    reg [8:0] write_count;
52    wire tx_full;
53    wire [15:0] fifodata;
54    wire rdreq;
55
56    reg [3:0] load_next;
57
58    // DAC Side of FIFO
59    assign    rdreq = ((load_next != channels) & !tx_empty);
60    
61    always @(posedge txclk)
62      if(reset)
63        begin
64           {tx_i_0,tx_q_0,tx_i_1,tx_q_1,tx_i_2,tx_q_2,tx_i_3,tx_q_3}
65             <= #1 128'h0;
66           load_next <= #1 4'd0;
67        end
68      else
69        if((load_next != channels) & !tx_empty)
70          begin
71             load_next <= #1 load_next + 4'd1;
72             case(load_next)
73               4'd0 : tx_i_0 <= #1 fifodata;
74               4'd1 : tx_q_0 <= #1 fifodata;
75               4'd2 : tx_i_1 <= #1 fifodata;
76               4'd3 : tx_q_1 <= #1 fifodata;
77               4'd4 : tx_i_2 <= #1 fifodata;
78               4'd5 : tx_q_2 <= #1 fifodata;
79               4'd6 : tx_i_3 <= #1 fifodata;
80               4'd7 : tx_q_3 <= #1 fifodata;
81             endcase // case(load_next)
82          end // if ((load_next != channels) & !tx_empty)
83        else if(txstrobe & (load_next == channels))
84          begin
85             load_next <= #1 4'd0;
86          end
87
88    // USB Side of FIFO
89    assign have_space = (txfifolevel <= (4095-256));
90
91    always @(posedge usbclk)
92      if(bus_reset)        // Use bus reset because this is on usbclk
93        write_count <= #1 0;
94      else if(WR & ~write_count[8])
95        write_count <= #1 write_count + 9'd1;
96      else
97        write_count <= #1 WR ? write_count : 9'b0;
98
99    // Detect Underruns
100    always @(posedge txclk)
101      if(reset)
102        tx_underrun <= 1'b0;
103      else if(txstrobe & (load_next != channels))
104        tx_underrun <= 1'b1;
105      else if(clear_status)
106        tx_underrun <= 1'b0;
107
108    // FIFO
109    fifo_4k txfifo 
110      ( .data ( usbdata ),
111        .wrreq ( WR & ~write_count[8] ),
112        .wrclk ( usbclk ),
113        
114        .q ( fifodata ),                 
115        .rdreq ( rdreq ),
116        .rdclk ( txclk ),
117        
118        .aclr ( reset ),  // asynch, so we can use either
119        
120        .rdempty ( tx_empty ),
121        .rdusedw (  ),
122        .wrfull ( tx_full ),
123        .wrusedw ( txfifolevel )
124        );
125    
126    // Debugging Aids
127    assign debugbus[0] = WR;
128    assign debugbus[1] = have_space;
129    assign debugbus[2] = tx_empty;
130    assign debugbus[3] = tx_full;
131    assign debugbus[4] = tx_underrun;
132    assign debugbus[5] = write_count[8];
133    assign debugbus[6] = txstrobe;
134    assign debugbus[7] = rdreq;
135    assign debugbus[11:8] = load_next;
136    
137 endmodule // tx_buffer
138