diff options
Diffstat (limited to 'fpga/usrp1/sdr_lib/rx_buffer.v')
-rw-r--r-- | fpga/usrp1/sdr_lib/rx_buffer.v | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/fpga/usrp1/sdr_lib/rx_buffer.v b/fpga/usrp1/sdr_lib/rx_buffer.v new file mode 100644 index 000000000..5541d2912 --- /dev/null +++ b/fpga/usrp1/sdr_lib/rx_buffer.v @@ -0,0 +1,237 @@ +// -*- 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, the fifo has 4096 lines of 18 bits each + +`include "../common/fpga_regs_common.v" +`include "../common/fpga_regs_standard.v" + +module rx_buffer + ( // Read/USB side + input usbclk, + input bus_reset, + output [15:0] usbdata, + input RD, + output reg have_pkt_rdy, + output reg rx_overrun, + input clear_status, + // Write/DSP side + input rxclk, + input reset, // DSP side reset (used here), do not reset registers + input rxstrobe, + input wire [3:0] channels, + input wire [15:0] ch_0, + input wire [15:0] ch_1, + input wire [15:0] ch_2, + input wire [15:0] ch_3, + input wire [15:0] ch_4, + input wire [15:0] ch_5, + input wire [15:0] ch_6, + input wire [15:0] ch_7, + // Settings, on rxclk also + input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe, + input reset_regs, //Only reset registers + output [31:0] debugbus + ); + + wire [15:0] fifodata, fifodata_8; + reg [15:0] fifodata_16; + + wire [11:0] rxfifolevel; + wire rx_full; + + wire bypass_hb, want_q; + wire [4:0] bitwidth; + wire [3:0] bitshift; + + setting_reg #(`FR_RX_FORMAT) sr_rxformat(.clock(rxclk),.reset(reset_regs), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({bypass_hb,want_q,bitwidth,bitshift})); + + // USB Read Side of FIFO + always @(negedge usbclk) + have_pkt_rdy <= (rxfifolevel >= 256); + + // 257 Bug Fix + reg [8:0] read_count; + always @(negedge usbclk) + if(bus_reset) + read_count <= 0; + else if(RD) + read_count <= read_count + 1; + else + read_count <= 0; + + // FIFO + wire ch0_in, ch0_out, iq_out; + assign ch0_in = (phase == 1); + + fifo_4k_18 rxfifo + ( // DSP Write Side + .data ( {ch0_in, phase[0], fifodata} ), + .wrreq (~rx_full & (phase != 0)), + .wrclk ( rxclk ), + .wrfull ( rx_full ), + .wrempty ( ), + .wrusedw ( ), + // USB Read Side + .q ( {ch0_out,iq_out,usbdata} ), + .rdreq ( RD & ~read_count[8] ), + .rdclk ( ~usbclk ), + .rdfull ( ), + .rdempty ( ), + .rdusedw ( rxfifolevel ), + // Async, shared + .aclr ( reset ) ); + + // DSP Write Side of FIFO + reg [15:0] ch_0_reg; + reg [15:0] ch_1_reg; + reg [15:0] ch_2_reg; + reg [15:0] ch_3_reg; + reg [15:0] ch_4_reg; + reg [15:0] ch_5_reg; + reg [15:0] ch_6_reg; + reg [15:0] ch_7_reg; + + always @(posedge rxclk) + if (rxstrobe) + begin + ch_0_reg <= ch_0; + ch_1_reg <= ch_1; + ch_2_reg <= ch_2; + ch_3_reg <= ch_3; + ch_4_reg <= ch_4; + ch_5_reg <= ch_5; + ch_6_reg <= ch_6; + ch_7_reg <= ch_7; + end + + reg [3:0] phase; + always @(posedge rxclk) + if(reset) + phase <= 4'd0; + else if(phase == 0) + begin + if(rxstrobe) + phase <= 4'd1; + end + else if(~rx_full) + if(phase == ((bitwidth == 5'd8) ? (channels>>1) : channels)) + phase <= 4'd0; + else + phase <= phase + 4'd1; + + assign fifodata = (bitwidth == 5'd8) ? fifodata_8 : fifodata_16; + + assign fifodata_8 = {round_8(top),round_8(bottom)}; + reg [15:0] top,bottom; + + function [7:0] round_8; + input [15:0] in_val; + + round_8 = in_val[15:8] + (in_val[15] & |in_val[7:0]); + endfunction // round_8 + + always @* + case(phase) + 4'd1 : begin + bottom = ch_0_reg; + top = ch_1_reg; + end + 4'd2 : begin + bottom = ch_2_reg; + top = ch_3_reg; + end + 4'd3 : begin + bottom = ch_4_reg; + top = ch_5_reg; + end + 4'd4 : begin + bottom = ch_6_reg; + top = ch_7_reg; + end + default : begin + top = 16'hFFFF; + bottom = 16'hFFFF; + end + endcase // case(phase) + + always @* + case(phase) + 4'd1 : fifodata_16 = ch_0_reg; + 4'd2 : fifodata_16 = ch_1_reg; + 4'd3 : fifodata_16 = ch_2_reg; + 4'd4 : fifodata_16 = ch_3_reg; + 4'd5 : fifodata_16 = ch_4_reg; + 4'd6 : fifodata_16 = ch_5_reg; + 4'd7 : fifodata_16 = ch_6_reg; + 4'd8 : fifodata_16 = ch_7_reg; + default : fifodata_16 = 16'hFFFF; + endcase // case(phase) + + // Detect overrun + reg clear_status_dsp, rx_overrun_dsp; + always @(posedge rxclk) + clear_status_dsp <= clear_status; + + always @(negedge usbclk) + rx_overrun <= rx_overrun_dsp; + + always @(posedge rxclk) + if(reset) + rx_overrun_dsp <= 1'b0; + else if(rxstrobe & (phase != 0)) + rx_overrun_dsp <= 1'b1; + else if(clear_status_dsp) + rx_overrun_dsp <= 1'b0; + + // Debug bus + // + // 15:0 rxclk domain => TXA 15:0 + // 31:16 usbclk domain => RXA 15:0 + + assign debugbus[0] = reset; + assign debugbus[1] = reset_regs; + assign debugbus[2] = rxstrobe; + assign debugbus[6:3] = channels; + assign debugbus[7] = rx_full; + assign debugbus[11:8] = phase; + assign debugbus[12] = ch0_in; + assign debugbus[13] = clear_status_dsp; + assign debugbus[14] = rx_overrun_dsp; + assign debugbus[15] = rxclk; + + assign debugbus[16] = bus_reset; + assign debugbus[17] = RD; + assign debugbus[18] = have_pkt_rdy; + assign debugbus[19] = rx_overrun; + assign debugbus[20] = read_count[0]; + assign debugbus[21] = read_count[8]; + assign debugbus[22] = ch0_out; + assign debugbus[23] = iq_out; + assign debugbus[24] = clear_status; + assign debugbus[30:25] = 0; + assign debugbus[31] = usbclk; + +endmodule // rx_buffer + |