mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
170 lines
4.5 KiB
Verilog
170 lines
4.5 KiB
Verilog
// -*- 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
|
|
|