aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp1/inband_lib
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-01-23 16:10:22 -0800
committerMartin Braun <martin.braun@ettus.com>2020-01-28 09:35:36 -0800
commitbafa9d95453387814ef25e6b6256ba8db2df612f (patch)
tree39ba24b5b67072d354775272e687796bb511848d /fpga/usrp1/inband_lib
parent3075b981503002df3115d5f1d0b97d2619ba30f2 (diff)
downloaduhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp1/inband_lib')
-rwxr-xr-xfpga/usrp1/inband_lib/chan_fifo_reader.v219
-rw-r--r--fpga/usrp1/inband_lib/channel_demux.v78
-rwxr-xr-xfpga/usrp1/inband_lib/channel_ram.v107
-rwxr-xr-xfpga/usrp1/inband_lib/cmd_reader.v305
-rwxr-xr-xfpga/usrp1/inband_lib/packet_builder.v152
-rwxr-xr-xfpga/usrp1/inband_lib/register_io.v82
-rwxr-xr-xfpga/usrp1/inband_lib/rx_buffer_inband.v209
-rwxr-xr-xfpga/usrp1/inband_lib/tx_buffer_inband.v143
-rw-r--r--fpga/usrp1/inband_lib/tx_packer.v119
-rwxr-xr-xfpga/usrp1/inband_lib/usb_packet_fifo.v112
10 files changed, 1526 insertions, 0 deletions
diff --git a/fpga/usrp1/inband_lib/chan_fifo_reader.v b/fpga/usrp1/inband_lib/chan_fifo_reader.v
new file mode 100755
index 000000000..69da9ec5a
--- /dev/null
+++ b/fpga/usrp1/inband_lib/chan_fifo_reader.v
@@ -0,0 +1,219 @@
+module chan_fifo_reader
+ (reset, tx_clock, tx_strobe, timestamp_clock, samples_format,
+ fifodata, pkt_waiting, rdreq, skip, tx_q, tx_i,
+ underrun, tx_empty, debug, rssi, threshhold, rssi_wait) ;
+
+ input wire reset ;
+ input wire tx_clock ;
+ input wire tx_strobe ; //signal to output tx_i and tx_q
+ input wire [31:0] timestamp_clock ; //current time
+ input wire [3:0] samples_format ;// not useful at this point
+ input wire [31:0] fifodata ; //the data input
+ input wire pkt_waiting ; //signal the next packet is ready
+ output reg rdreq ; //actually an ack to the current fifodata
+ output reg skip ; //finish reading current packet
+ output reg [15:0] tx_q ; //top 16 bit output of fifodata
+ output reg [15:0] tx_i ; //bottom 16 bit output of fifodata
+ output reg underrun ;
+ output reg tx_empty ; //cause 0 to be the output
+ input wire [31:0] rssi;
+ input wire [31:0] threshhold;
+ input wire [31:0] rssi_wait;
+
+ output wire [14:0] debug;
+ assign debug = {7'd0, rdreq, skip, reader_state, pkt_waiting, tx_strobe, tx_clock};
+
+ //Samples format
+ // 16 bits interleaved complex samples
+ `define QI16 4'b0
+
+ // States
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter TIMESTAMP = 3'd2;
+ parameter WAIT = 3'd3;
+ parameter WAITSTROBE = 3'd4;
+ parameter SEND = 3'd5;
+
+ // Header format
+ `define PAYLOAD 8:2
+ `define ENDOFBURST 27
+ `define STARTOFBURST 28
+ `define RSSI_FLAG 26
+
+
+ /* State registers */
+ reg [2:0] reader_state;
+ /* Local registers */
+ reg [6:0] payload_len;
+ reg [6:0] read_len;
+ reg [31:0] timestamp;
+ reg burst;
+ reg trash;
+ reg rssi_flag;
+ reg [31:0] time_wait;
+
+ always @(posedge tx_clock)
+ begin
+ if (reset)
+ begin
+ reader_state <= IDLE;
+ rdreq <= 0;
+ skip <= 0;
+ underrun <= 0;
+ burst <= 0;
+ tx_empty <= 1;
+ tx_q <= 0;
+ tx_i <= 0;
+ trash <= 0;
+ rssi_flag <= 0;
+ time_wait <= 0;
+ end
+ else
+ begin
+ case (reader_state)
+ IDLE:
+ begin
+ /*
+ * reset all the variables and wait for a tx_strobe
+ * it is assumed that the ram connected to this fifo_reader
+ * is a short hand fifo meaning that the header to the next packet
+ * is already available to this fifo_reader when pkt_waiting is on
+ */
+ skip <=0;
+ time_wait <= 0;
+ if (pkt_waiting == 1)
+ begin
+ reader_state <= HEADER;
+ rdreq <= 1;
+ underrun <= 0;
+ end
+ if (burst == 1 && pkt_waiting == 0)
+ underrun <= 1;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ end
+
+ /* Process header */
+ HEADER:
+ begin
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+
+ rssi_flag <= fifodata[`RSSI_FLAG]&fifodata[`STARTOFBURST];
+ //Check Start/End burst flag
+ if (fifodata[`STARTOFBURST] == 1
+ && fifodata[`ENDOFBURST] == 1)
+ burst <= 0;
+ else if (fifodata[`STARTOFBURST] == 1)
+ burst <= 1;
+ else if (fifodata[`ENDOFBURST] == 1)
+ burst <= 0;
+
+ if (trash == 1 && fifodata[`STARTOFBURST] == 0)
+ begin
+ skip <= 1;
+ reader_state <= IDLE;
+ rdreq <= 0;
+ end
+ else
+ begin
+ payload_len <= fifodata[`PAYLOAD] ;
+ read_len <= 0;
+ rdreq <= 1;
+ reader_state <= TIMESTAMP;
+ end
+ end
+
+ TIMESTAMP:
+ begin
+ timestamp <= fifodata;
+ reader_state <= WAIT;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ rdreq <= 0;
+ end
+
+ // Decide if we wait, send or discard samples
+ WAIT:
+ begin
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+
+ time_wait <= time_wait + 32'd1;
+ // Outdated
+ if ((timestamp < timestamp_clock) ||
+ (time_wait >= rssi_wait && rssi_wait != 0 && rssi_flag))
+ begin
+ trash <= 1;
+ reader_state <= IDLE;
+ skip <= 1;
+ end
+ // Let's send it
+ else if (timestamp == timestamp_clock
+ || timestamp == 32'hFFFFFFFF)
+ begin
+ if (rssi <= threshhold || rssi_flag == 0)
+ begin
+ trash <= 0;
+ reader_state <= WAITSTROBE;
+ end
+ else
+ reader_state <= WAIT;
+ end
+ else
+ reader_state <= WAIT;
+ end
+
+ // Wait for the transmit chain to be ready
+ WAITSTROBE:
+ begin
+ // If end of payload...
+ if (read_len == payload_len)
+ begin
+ reader_state <= IDLE;
+ skip <= 1;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ end
+ else if (tx_strobe == 1)
+ begin
+ reader_state <= SEND;
+ rdreq <= 1;
+ end
+ end
+
+ // Send the samples to the tx_chain
+ SEND:
+ begin
+ reader_state <= WAITSTROBE;
+ read_len <= read_len + 7'd1;
+ tx_empty <= 0;
+ rdreq <= 0;
+
+ case(samples_format)
+ `QI16:
+ begin
+ tx_i <= fifodata[15:0];
+ tx_q <= fifodata[31:16];
+ end
+
+ // Assume 16 bits complex samples by default
+ default:
+ begin
+ tx_i <= fifodata[15:0];
+ tx_q <= fifodata[31:16];
+ end
+ endcase
+ end
+
+ default:
+ begin
+ //error handling
+ reader_state <= IDLE;
+ end
+ endcase
+ end
+ end
+
+endmodule
diff --git a/fpga/usrp1/inband_lib/channel_demux.v b/fpga/usrp1/inband_lib/channel_demux.v
new file mode 100644
index 000000000..cca5cdb65
--- /dev/null
+++ b/fpga/usrp1/inband_lib/channel_demux.v
@@ -0,0 +1,78 @@
+module channel_demux
+ #(parameter NUM_CHAN = 2) ( //usb Side
+ input [31:0]usbdata_final,
+ input WR_final,
+ // TX Side
+ input reset,
+ input txclk,
+ output reg [NUM_CHAN:0] WR_channel,
+ output reg [31:0] ram_data,
+ output reg [NUM_CHAN:0] WR_done_channel );
+ /* Parse header and forward to ram */
+
+ reg [2:0]reader_state;
+ reg [4:0]channel ;
+ reg [6:0]read_length ;
+
+ // States
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter WAIT = 3'd2;
+ parameter FORWARD = 3'd3;
+
+ `define CHANNEL 20:16
+ `define PKT_SIZE 127
+ wire [4:0] true_channel;
+ assign true_channel = (usbdata_final[`CHANNEL] == 5'h1f) ?
+ NUM_CHAN : (usbdata_final[`CHANNEL]);
+
+ always @(posedge txclk)
+ begin
+ if (reset)
+ begin
+ reader_state <= IDLE;
+ WR_channel <= 0;
+ WR_done_channel <= 0;
+ end
+ else
+ case (reader_state)
+ IDLE: begin
+ if (WR_final)
+ reader_state <= HEADER;
+ end
+
+ // Store channel and forware header
+ HEADER: begin
+ channel <= true_channel;
+ WR_channel[true_channel] <= 1;
+ ram_data <= usbdata_final;
+ read_length <= 7'd0 ;
+
+ reader_state <= WAIT;
+ end
+
+ WAIT: begin
+ WR_channel[channel] <= 0;
+
+ if (read_length == `PKT_SIZE)
+ reader_state <= IDLE;
+ else if (WR_final)
+ reader_state <= FORWARD;
+ end
+
+ FORWARD: begin
+ WR_channel[channel] <= 1;
+ ram_data <= usbdata_final;
+ read_length <= read_length + 7'd1;
+
+ reader_state <= WAIT;
+ end
+
+ default:
+ begin
+ //error handling
+ reader_state <= IDLE;
+ end
+ endcase
+ end
+endmodule
diff --git a/fpga/usrp1/inband_lib/channel_ram.v b/fpga/usrp1/inband_lib/channel_ram.v
new file mode 100755
index 000000000..9621246c5
--- /dev/null
+++ b/fpga/usrp1/inband_lib/channel_ram.v
@@ -0,0 +1,107 @@
+module channel_ram
+ ( // System
+ input txclk, input reset,
+ // USB side
+ input [31:0] datain, input WR, input WR_done, output have_space,
+ // Reader side
+ output [31:0] dataout, input RD, input RD_done, output packet_waiting);
+
+ reg [6:0] wr_addr, rd_addr;
+ reg [1:0] which_ram_wr, which_ram_rd;
+ reg [2:0] nb_packets;
+
+ reg [31:0] ram0 [0:127];
+ reg [31:0] ram1 [0:127];
+ reg [31:0] ram2 [0:127];
+ reg [31:0] ram3 [0:127];
+
+ reg [31:0] dataout0;
+ reg [31:0] dataout1;
+ reg [31:0] dataout2;
+ reg [31:0] dataout3;
+
+ wire wr_done_int;
+ wire rd_done_int;
+ wire [6:0] rd_addr_final;
+ wire [1:0] which_ram_rd_final;
+
+ // USB side
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
+
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
+
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
+
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
+
+ assign wr_done_int = ((WR && (wr_addr == 7'd127)) || WR_done);
+
+ always @(posedge txclk)
+ if(reset)
+ wr_addr <= 0;
+ else if (WR_done)
+ wr_addr <= 0;
+ else if (WR)
+ wr_addr <= wr_addr + 7'd1;
+
+ always @(posedge txclk)
+ if(reset)
+ which_ram_wr <= 0;
+ else if (wr_done_int)
+ which_ram_wr <= which_ram_wr + 2'd1;
+
+ assign have_space = (nb_packets < 3'd3);
+
+ // Reader side
+ // short hand fifo
+ // rd_addr_final is what rd_addr is going to be next clock cycle
+ // which_ram_rd_final is what which_ram_rd is going to be next clock cycle
+ always @(posedge txclk) dataout0 <= ram0[rd_addr_final];
+ always @(posedge txclk) dataout1 <= ram1[rd_addr_final];
+ always @(posedge txclk) dataout2 <= ram2[rd_addr_final];
+ always @(posedge txclk) dataout3 <= ram3[rd_addr_final];
+
+ assign dataout = (which_ram_rd_final[1]) ?
+ (which_ram_rd_final[0] ? dataout3 : dataout2) :
+ (which_ram_rd_final[0] ? dataout1 : dataout0);
+
+ //RD_done is the only way to signal the end of one packet
+ assign rd_done_int = RD_done;
+
+ always @(posedge txclk)
+ if (reset)
+ rd_addr <= 0;
+ else if (RD_done)
+ rd_addr <= 0;
+ else if (RD)
+ rd_addr <= rd_addr + 7'd1;
+
+ assign rd_addr_final = (reset|RD_done) ? (6'd0) :
+ ((RD)?(rd_addr+7'd1):rd_addr);
+
+ always @(posedge txclk)
+ if (reset)
+ which_ram_rd <= 0;
+ else if (rd_done_int)
+ which_ram_rd <= which_ram_rd + 2'd1;
+
+ assign which_ram_rd_final = (reset) ? (2'd0):
+ ((rd_done_int) ? (which_ram_rd + 2'd1) : which_ram_rd);
+
+ //packet_waiting is set to zero if rd_done_int is high
+ //because there is no guarantee that nb_packets will be pos.
+
+ assign packet_waiting = (nb_packets > 1) | ((nb_packets == 1)&(~rd_done_int));
+ always @(posedge txclk)
+ if (reset)
+ nb_packets <= 0;
+ else if (wr_done_int & ~rd_done_int)
+ nb_packets <= nb_packets + 3'd1;
+ else if (rd_done_int & ~wr_done_int)
+ nb_packets <= nb_packets - 3'd1;
+
+endmodule
diff --git a/fpga/usrp1/inband_lib/cmd_reader.v b/fpga/usrp1/inband_lib/cmd_reader.v
new file mode 100755
index 000000000..b69ea02b7
--- /dev/null
+++ b/fpga/usrp1/inband_lib/cmd_reader.v
@@ -0,0 +1,305 @@
+module cmd_reader
+ (//System
+ input reset, input txclk, input [31:0] timestamp_clock,
+ //FX2 Side
+ output reg skip, output reg rdreq,
+ input [31:0] fifodata, input pkt_waiting,
+ //Rx side
+ input rx_WR_enabled, output reg [15:0] rx_databus,
+ output reg rx_WR, output reg rx_WR_done,
+ //register io
+ input wire [31:0] reg_data_out, output reg [31:0] reg_data_in,
+ output reg [6:0] reg_addr, output reg [1:0] reg_io_enable,
+ output wire [14:0] debug, output reg stop, output reg [15:0] stop_time);
+
+ // States
+ parameter IDLE = 4'd0;
+ parameter HEADER = 4'd1;
+ parameter TIMESTAMP = 4'd2;
+ parameter WAIT = 4'd3;
+ parameter TEST = 4'd4;
+ parameter SEND = 4'd5;
+ parameter PING = 4'd6;
+ parameter WRITE_REG = 4'd7;
+ parameter WRITE_REG_MASKED = 4'd8;
+ parameter READ_REG = 4'd9;
+ parameter DELAY = 4'd14;
+
+ `define OP_PING_FIXED 8'd0
+ `define OP_PING_FIXED_REPLY 8'd1
+ `define OP_WRITE_REG 8'd2
+ `define OP_WRITE_REG_MASKED 8'd3
+ `define OP_READ_REG 8'd4
+ `define OP_READ_REG_REPLY 8'd5
+ `define OP_DELAY 8'd12
+
+ reg [6:0] payload;
+ reg [6:0] payload_read;
+ reg [3:0] state;
+ reg [15:0] high;
+ reg [15:0] low;
+ reg pending;
+ reg [31:0] value0;
+ reg [31:0] value1;
+ reg [31:0] value2;
+ reg [1:0] lines_in;
+ reg [1:0] lines_out;
+ reg [1:0] lines_out_total;
+
+ `define JITTER 5
+ `define OP_CODE 31:24
+ `define PAYLOAD 8:2
+
+ wire [7:0] ops;
+ assign ops = value0[`OP_CODE];
+ assign debug = {state[3:0], lines_out[1:0], pending, rx_WR, rx_WR_enabled, value0[2:0], ops[2:0]};
+
+ always @(posedge txclk)
+ if (reset)
+ begin
+ pending <= 0;
+ state <= IDLE;
+ skip <= 0;
+ rdreq <= 0;
+ rx_WR <= 0;
+ reg_io_enable <= 0;
+ reg_data_in <= 0;
+ reg_addr <= 0;
+ stop <= 0;
+ end
+ else case (state)
+ IDLE :
+ begin
+ payload_read <= 0;
+ skip <= 0;
+ lines_in <= 0;
+ if(pkt_waiting)
+ begin
+ state <= HEADER;
+ rdreq <= 1;
+ end
+ end
+
+ HEADER :
+ begin
+ payload <= fifodata[`PAYLOAD];
+ state <= TIMESTAMP;
+ end
+
+ TIMESTAMP :
+ begin
+ value0 <= fifodata;
+ state <= WAIT;
+ rdreq <= 0;
+ end
+
+ WAIT :
+ begin
+ // Let's send it
+ if ((value0 <= timestamp_clock + `JITTER
+ && value0 > timestamp_clock)
+ || value0 == 32'hFFFFFFFF)
+ state <= TEST;
+ // Wait a little bit more
+ else if (value0 > timestamp_clock + `JITTER)
+ state <= WAIT;
+ // Outdated
+ else if (value0 < timestamp_clock)
+ begin
+ state <= IDLE;
+ skip <= 1;
+ end
+ end
+
+ TEST :
+ begin
+ reg_io_enable <= 0;
+ rx_WR <= 0;
+ rx_WR_done <= 1;
+ stop <= 0;
+ if (payload_read == payload)
+ begin
+ skip <= 1;
+ state <= IDLE;
+ rdreq <= 0;
+ end
+ else
+ begin
+ value0 <= fifodata;
+ lines_in <= 2'd1;
+ rdreq <= 1;
+ payload_read <= payload_read + 7'd1;
+ lines_out <= 0;
+ case (fifodata[`OP_CODE])
+ `OP_PING_FIXED:
+ begin
+ state <= PING;
+ end
+ `OP_WRITE_REG:
+ begin
+ state <= WRITE_REG;
+ pending <= 1;
+ end
+ `OP_WRITE_REG_MASKED:
+ begin
+ state <= WRITE_REG_MASKED;
+ pending <= 1;
+ end
+ `OP_READ_REG:
+ begin
+ state <= READ_REG;
+ end
+ `OP_DELAY:
+ begin
+ state <= DELAY;
+ end
+ default:
+ begin
+ //error, skip this packet
+ skip <= 1;
+ state <= IDLE;
+ end
+ endcase
+ end
+ end
+
+ SEND:
+ begin
+ rdreq <= 0;
+ rx_WR_done <= 0;
+ if (pending)
+ begin
+ rx_WR <= 1;
+ rx_databus <= high;
+ pending <= 0;
+ if (lines_out == lines_out_total)
+ state <= TEST;
+ else case (ops)
+ `OP_READ_REG:
+ begin
+ state <= READ_REG;
+ end
+ default:
+ begin
+ state <= TEST;
+ end
+ endcase
+ end
+ else
+ begin
+ if (rx_WR_enabled)
+ begin
+ rx_WR <= 1;
+ rx_databus <= low;
+ pending <= 1;
+ lines_out <= lines_out + 2'd1;
+ end
+ else
+ rx_WR <= 0;
+ end
+ end
+
+ PING:
+ begin
+ rx_WR <= 0;
+ rdreq <= 0;
+ rx_WR_done <= 0;
+ lines_out_total <= 2'd1;
+ pending <= 0;
+ state <= SEND;
+ high <= {`OP_PING_FIXED_REPLY, 8'd2};
+ low <= value0[15:0];
+ end
+
+ READ_REG:
+ begin
+ rx_WR <= 0;
+ rx_WR_done <= 0;
+ rdreq <= 0;
+ lines_out_total <= 2'd2;
+ pending <= 0;
+ state <= SEND;
+ if (lines_out == 0)
+ begin
+ high <= {`OP_READ_REG_REPLY, 8'd6};
+ low <= value0[15:0];
+ reg_io_enable <= 2'd3;
+ reg_addr <= value0[6:0];
+ end
+ else
+ begin
+ high <= reg_data_out[31:16];
+ low <= reg_data_out[15:0];
+ end
+ end
+
+ WRITE_REG:
+ begin
+ rx_WR <= 0;
+ if (pending)
+ pending <= 0;
+ else
+ begin
+ if (lines_in == 2'd1)
+ begin
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value1 <= fifodata;
+ rdreq <= 0;
+ end
+ else
+ begin
+ reg_io_enable <= 2'd2;
+ reg_data_in <= value1;
+ reg_addr <= value0[6:0];
+ state <= TEST;
+ end
+ end
+ end
+
+ WRITE_REG_MASKED:
+ begin
+ rx_WR <= 0;
+ if (pending)
+ pending <= 0;
+ else
+ begin
+ if (lines_in == 2'd1)
+ begin
+ rdreq <= 1;
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value1 <= fifodata;
+ end
+ else if (lines_in == 2'd2)
+ begin
+ rdreq <= 0;
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value2 <= fifodata;
+ end
+ else
+ begin
+ reg_io_enable <= 2'd2;
+ reg_data_in <= (value1 & value2);
+ reg_addr <= value0[6:0];
+ state <= TEST;
+ end
+ end
+ end
+
+ DELAY :
+ begin
+ rdreq <= 0;
+ stop <= 1;
+ stop_time <= value0[15:0];
+ state <= TEST;
+ end
+
+ default :
+ begin
+ //error state handling
+ state <= IDLE;
+ end
+ endcase
+endmodule
diff --git a/fpga/usrp1/inband_lib/packet_builder.v b/fpga/usrp1/inband_lib/packet_builder.v
new file mode 100755
index 000000000..2c9122394
--- /dev/null
+++ b/fpga/usrp1/inband_lib/packet_builder.v
@@ -0,0 +1,152 @@
+module packet_builder #(parameter NUM_CHAN = 2)(
+ // System
+ input rxclk,
+ input reset,
+ input [31:0] timestamp_clock,
+ input [3:0] channels,
+ // ADC side
+ input [15:0]chan_fifodata,
+ input [NUM_CHAN:0]chan_empty,
+ input [9:0]chan_usedw,
+ output reg [3:0]rd_select,
+ output reg chan_rdreq,
+ // FX2 side
+ output reg WR,
+ output reg [15:0]fifodata,
+ input have_space,
+ input wire [31:0]rssi_0, input wire [31:0]rssi_1, input wire [31:0]rssi_2,
+ input wire [31:0]rssi_3, output wire [7:0] debugbus,
+ input [NUM_CHAN:0] underrun);
+
+
+ // States
+ `define IDLE 3'd0
+ `define HEADER1 3'd1
+ `define HEADER2 3'd2
+ `define TIMESTAMP 3'd3
+ `define FORWARD 3'd4
+
+ `define MAXPAYLOAD 504
+
+ `define PAYLOAD_LEN 8:0
+ `define TAG 12:9
+ `define MBZ 15:13
+
+ `define CHAN 4:0
+ `define RSSI 10:5
+ `define BURST 12:11
+ `define DROPPED 13
+ `define UNDERRUN 14
+ `define OVERRUN 15
+
+ reg [NUM_CHAN:0] overrun;
+ reg [2:0] state;
+ reg [8:0] read_length;
+ reg [8:0] payload_len;
+ reg timestamp_complete;
+ reg [3:0] check_next;
+
+ wire [31:0] true_rssi;
+ wire [4:0] true_channel;
+ wire ready_to_send;
+
+ assign debugbus = {chan_empty[0], rd_select[0], have_space,
+ (chan_usedw >= 10'd504), (chan_usedw ==0),
+ ready_to_send, state[1:0]};
+
+ assign true_rssi = (rd_select[1]) ? ((rd_select[0]) ? rssi_3:rssi_2) :
+ ((rd_select[0]) ? rssi_1:rssi_0);
+ assign true_channel = (check_next == 4'd0 ? 5'h1f : {1'd0, check_next - 4'd1});
+ assign ready_to_send = (chan_usedw >= 10'd504) || (chan_usedw == 0) ||
+ ((rd_select == NUM_CHAN)&&(chan_usedw > 0));
+
+ always @(posedge rxclk)
+ begin
+ if (reset)
+ begin
+ overrun <= 0;
+ WR <= 0;
+ rd_select <= 0;
+ chan_rdreq <= 0;
+ timestamp_complete <= 0;
+ check_next <= 0;
+ state <= `IDLE;
+ end
+ else case (state)
+ `IDLE: begin
+ chan_rdreq <= #1 0;
+ //check if the channel is full
+ if(~chan_empty[check_next])
+ begin
+ if (have_space)
+ begin
+ //transmit if the usb buffer have space
+ //check if we should send
+ if (ready_to_send)
+ state <= #1 `HEADER1;
+
+ overrun[check_next] <= 0;
+ end
+ else
+ begin
+ state <= #1 `IDLE;
+ overrun[check_next] <= 1;
+ end
+ rd_select <= #1 check_next;
+ end
+ check_next <= #1 (check_next == channels ? 4'd0 : check_next + 4'd1);
+ end
+
+ `HEADER1: begin
+ fifodata[`PAYLOAD_LEN] <= #1 9'd504;
+ payload_len <= #1 9'd504;
+ fifodata[`TAG] <= #1 0;
+ fifodata[`MBZ] <= #1 0;
+ WR <= #1 1;
+
+ state <= #1 `HEADER2;
+ read_length <= #1 0;
+ end
+
+ `HEADER2: begin
+ fifodata[`CHAN] <= #1 true_channel;
+ fifodata[`RSSI] <= #1 true_rssi[5:0];
+ fifodata[`BURST] <= #1 0;
+ fifodata[`DROPPED] <= #1 0;
+ fifodata[`UNDERRUN] <= #1 (check_next == 0) ? 1'b0 : underrun[true_channel];
+ fifodata[`OVERRUN] <= #1 (check_next == 0) ? 1'b0 : overrun[true_channel];
+ state <= #1 `TIMESTAMP;
+ end
+
+ `TIMESTAMP: begin
+ fifodata <= #1 (timestamp_complete ? timestamp_clock[31:16] : timestamp_clock[15:0]);
+ timestamp_complete <= #1 ~timestamp_complete;
+
+ if (~timestamp_complete)
+ chan_rdreq <= #1 1;
+
+ state <= #1 (timestamp_complete ? `FORWARD : `TIMESTAMP);
+ end
+
+ `FORWARD: begin
+ read_length <= #1 read_length + 9'd2;
+ fifodata <= #1 (read_length >= payload_len ? 16'hDEAD : chan_fifodata);
+
+ if (read_length >= `MAXPAYLOAD)
+ begin
+ WR <= #1 0;
+ state <= #1 `IDLE;
+ chan_rdreq <= #1 0;
+ end
+ else if (read_length == payload_len - 4)
+ chan_rdreq <= #1 0;
+ end
+
+ default: begin
+ //handling error state
+ state <= `IDLE;
+ end
+ endcase
+ end
+endmodule
+
diff --git a/fpga/usrp1/inband_lib/register_io.v b/fpga/usrp1/inband_lib/register_io.v
new file mode 100755
index 000000000..2b0cd1732
--- /dev/null
+++ b/fpga/usrp1/inband_lib/register_io.v
@@ -0,0 +1,82 @@
+module register_io
+ (clk, reset, enable, addr, datain, dataout, debugbus, addr_wr, data_wr, strobe_wr,
+ rssi_0, rssi_1, rssi_2, rssi_3, threshhold, rssi_wait, reg_0, reg_1, reg_2, reg_3,
+ debug_en, misc, txmux);
+
+ input clk;
+ input reset;
+ input wire [1:0] enable;
+ input wire [6:0] addr;
+ input wire [31:0] datain;
+ output reg [31:0] dataout;
+ output wire [15:0] debugbus;
+ output reg [6:0] addr_wr;
+ output reg [31:0] data_wr;
+ output wire strobe_wr;
+ input wire [31:0] rssi_0;
+ input wire [31:0] rssi_1;
+ input wire [31:0] rssi_2;
+ input wire [31:0] rssi_3;
+ output wire [31:0] threshhold;
+ output wire [31:0] rssi_wait;
+ input wire [15:0] reg_0;
+ input wire [15:0] reg_1;
+ input wire [15:0] reg_2;
+ input wire [15:0] reg_3;
+ input wire [3:0] debug_en;
+ input wire [7:0] misc;
+ input wire [31:0] txmux;
+
+ reg strobe;
+ wire [31:0] out[2:1];
+ assign debugbus = {clk, enable, addr[2:0], datain[4:0], dataout[4:0]};
+ assign threshhold = out[1];
+ assign rssi_wait = out[2];
+ assign strobe_wr = strobe;
+
+ always @(*)
+ if (reset | ~enable[1])
+ begin
+ strobe <= 0;
+ dataout <= 0;
+ end
+ else
+ begin
+ if (enable[0])
+ begin
+ //read
+ if (addr <= 7'd52 && addr > 7'd50)
+ dataout <= out[addr-7'd50];
+ else
+ dataout <= 32'hFFFFFFFF;
+ strobe <= 0;
+ end
+ else
+ begin
+ //write
+ dataout <= dataout;
+ strobe <= 1;
+ data_wr <= datain;
+ addr_wr <= addr;
+ end
+ end
+
+//register declarations
+ /*setting_reg #(50) setting_reg0(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[0]));*/
+ setting_reg #(51) setting_reg1(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[1]));
+ setting_reg #(52) setting_reg2(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[2]));
+ /*setting_reg #(53) setting_reg3(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[3]));
+ setting_reg #(54) setting_reg4(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[4]));
+ setting_reg #(55) setting_reg5(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[5]));
+ setting_reg #(56) setting_reg6(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[6]));
+ setting_reg #(57) setting_reg7(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[7]));*/
+
+endmodule
diff --git a/fpga/usrp1/inband_lib/rx_buffer_inband.v b/fpga/usrp1/inband_lib/rx_buffer_inband.v
new file mode 100755
index 000000000..6459f7025
--- /dev/null
+++ b/fpga/usrp1/inband_lib/rx_buffer_inband.v
@@ -0,0 +1,209 @@
+//`include "../common/fpga_regs_common.v"
+//`include "../common/fpga_regs_standard.v"
+module rx_buffer_inband
+ ( input usbclk,
+ input bus_reset,
+ input reset, // DSP side reset (used here), do not reset registers
+ input reset_regs, //Only reset registers
+ output [15:0] usbdata,
+ input RD,
+ output wire have_pkt_rdy,
+ output reg rx_overrun,
+ 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,
+ input rxclk,
+ input rxstrobe,
+ input clear_status,
+ input [6:0] serial_addr,
+ input [31:0] serial_data,
+ input serial_strobe,
+ output wire [15:0] debugbus,
+
+ //Connection with tx_inband
+ input rx_WR,
+ input [15:0] rx_databus,
+ input rx_WR_done,
+ output reg rx_WR_enabled,
+ //signal strength
+ input wire [31:0] rssi_0, input wire [31:0] rssi_1,
+ input wire [31:0] rssi_2, input wire [31:0] rssi_3,
+ input wire [1:0] tx_underrun
+ );
+
+ parameter NUM_CHAN = 1;
+ genvar i ;
+
+ // FX2 Bug Fix
+ reg [8:0] read_count;
+ always @(negedge usbclk)
+ if(bus_reset)
+ read_count <= #1 9'd0;
+ else if(RD & ~read_count[8])
+ read_count <= #1 read_count + 9'd1;
+ else
+ read_count <= #1 RD ? read_count : 9'b0;
+
+ // Time counter
+ reg [31:0] timestamp_clock;
+ always @(posedge rxclk)
+ if (reset)
+ timestamp_clock <= 0;
+ else
+ timestamp_clock <= timestamp_clock + 1;
+
+ // USB side fifo
+ wire [11:0] rdusedw;
+ wire [11:0] wrusedw;
+ wire [15:0] fifodata;
+ wire [15:0] fifodata_il[0:NUM_CHAN];
+ wire WR;
+ wire have_space;
+ reg sel;
+ reg wr;
+
+ always@(posedge rxclk)
+ begin
+ if(reset)
+ begin
+ sel<=1;
+ wr<=0;
+ end
+ else if(rxstrobe)
+ begin
+ sel<=0;
+ wr<=1;
+ end
+ else if(wr&~sel)
+ sel<=1;
+ else if(wr&sel)
+ wr<=0;
+ else
+ wr<=0;
+ end
+
+ assign fifodata_il[0] = (sel)?ch_1:ch_0;
+ assign fifodata_il[1] = (sel)?ch_3:ch_2;
+
+ fifo_4kx16_dc rx_usb_fifo (
+ .aclr ( reset ),
+ .data ( fifodata ),
+ .rdclk ( ~usbclk ),
+ .rdreq ( RD & ~read_count[8] ),
+ .wrclk ( rxclk ),
+ .wrreq ( WR ),
+ .q ( usbdata ),
+ .rdempty ( ),
+ .rdusedw ( rdusedw ),
+ .wrfull ( ),
+ .wrusedw ( wrusedw ) );
+
+ assign have_pkt_rdy = (rdusedw >= 12'd256);
+ assign have_space = (wrusedw < 12'd760);
+
+ // Rx side fifos
+ // These are of size [NUM_CHAN:0] because the extra channel is used for the
+ // RX command channel. If there were no command channel, they would be
+ // NUM_CHAN-1.
+ wire chan_rdreq;
+ wire [15:0] chan_fifodata;
+ wire [9:0] chan_usedw;
+ wire [NUM_CHAN:0] chan_empty;
+ wire [3:0] rd_select;
+ wire [NUM_CHAN:0] rx_full;
+
+ packet_builder #(NUM_CHAN) rx_pkt_builer (
+ .rxclk ( rxclk ),
+ .reset ( reset ),
+ .timestamp_clock ( timestamp_clock ),
+ .channels ( NUM_CHAN ),
+ .chan_rdreq ( chan_rdreq ),
+ .chan_fifodata ( chan_fifodata ),
+ .chan_empty ( chan_empty ),
+ .rd_select ( rd_select ),
+ .chan_usedw ( chan_usedw ),
+ .WR ( WR ),
+ .fifodata ( fifodata ),
+ .have_space ( have_space ),
+ .rssi_0(rssi_0), .rssi_1(rssi_1),
+ .rssi_2(rssi_2),.rssi_3(rssi_3), .debugbus(debug),
+ .underrun(tx_underrun));
+
+ // Detect overrun
+ always @(posedge rxclk)
+ if(reset)
+ rx_overrun <= 1'b0;
+ else if(rx_full[0])
+ rx_overrun <= 1'b1;
+ else if(clear_status)
+ rx_overrun <= 1'b0;
+
+
+ // FIXME: what is the purpose of these two lines?
+ wire [15:0]ch[NUM_CHAN:0];
+ assign ch[0] = ch_0;
+
+ wire cmd_empty;
+
+ always @(posedge rxclk)
+ if(reset)
+ rx_WR_enabled <= 1;
+ else if(cmd_empty)
+ rx_WR_enabled <= 1;
+ else if(rx_WR_done)
+ rx_WR_enabled <= 0;
+
+
+ // Of Size 0:NUM_CHAN due to extra command channel.
+ wire [15:0] dataout [0:NUM_CHAN];
+ wire [9:0] usedw [0:NUM_CHAN];
+ wire empty[0:NUM_CHAN];
+
+ generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+ begin : generate_channel_fifos
+
+ wire rdreq;
+
+ assign rdreq = (rd_select == i) & chan_rdreq;
+
+ fifo_1kx16 rx_chan_fifo (
+ .aclr ( reset ),
+ .clock ( rxclk ),
+ .data ( fifodata_il[i] ),
+ .rdreq ( rdreq ),
+ .wrreq ( ~rx_full[i] & wr),
+ .empty (empty[i]),
+ .full (rx_full[i]),
+ .q ( dataout[i]),
+ .usedw ( usedw[i]),
+ .almost_empty(chan_empty[i])
+ );
+ end
+ endgenerate
+
+ wire [7:0] debug;
+
+ fifo_1kx16 rx_cmd_fifo (
+ .aclr ( reset ),
+ .clock ( rxclk ),
+ .data ( rx_databus ),
+ .rdreq ( (rd_select == NUM_CHAN) & chan_rdreq ),
+ .wrreq ( rx_WR & rx_WR_enabled),
+ .empty ( cmd_empty),
+ .full ( rx_full[NUM_CHAN] ),
+ .q ( dataout[NUM_CHAN]),
+ .usedw ( usedw[NUM_CHAN] )
+ );
+
+ assign chan_empty[NUM_CHAN] = cmd_empty | rx_WR_enabled;
+ assign chan_fifodata = dataout[rd_select];
+ assign chan_usedw = usedw[rd_select];
+ assign debugbus = {4'd0, rxclk, rxstrobe, rx_full[0], rx_full[1], sel, wr};
+
+endmodule
diff --git a/fpga/usrp1/inband_lib/tx_buffer_inband.v b/fpga/usrp1/inband_lib/tx_buffer_inband.v
new file mode 100755
index 000000000..2dd75f42f
--- /dev/null
+++ b/fpga/usrp1/inband_lib/tx_buffer_inband.v
@@ -0,0 +1,143 @@
+module tx_buffer_inband
+ ( //System
+ input wire usbclk, input wire bus_reset, input wire reset,
+ input wire [15:0] usbdata, output wire have_space, input wire [3:0] channels,
+ //output transmit signals
+ output wire [15:0] tx_i_0, output wire [15:0] tx_q_0,
+ output wire [15:0] tx_i_1, output wire [15:0] tx_q_1,
+ output wire [15:0] tx_i_2, output wire [15:0] tx_q_2,
+ output wire [15:0] tx_i_3, output wire [15:0] tx_q_3,
+ input wire txclk, input wire txstrobe, input wire WR,
+ input wire clear_status, output wire tx_empty, output wire [15:0] debugbus,
+ //command reader io
+ output wire [15:0] rx_databus, output wire rx_WR, output wire rx_WR_done,
+ input wire rx_WR_enabled,
+ //register io
+ output wire [1:0] reg_io_enable, output wire [31:0] reg_data_in, output wire [6:0] reg_addr,
+ input wire [31:0] reg_data_out,
+ //input characteristic signals
+ input wire [31:0] rssi_0, input wire [31:0] rssi_1, input wire [31:0] rssi_2,
+ input wire [31:0] rssi_3, input wire [31:0] rssi_wait, input wire [31:0] threshhold,
+ output wire [1:0] tx_underrun,
+ //system stop
+ output wire stop, output wire [15:0] stop_time);
+
+ parameter NUM_CHAN = 1 ;
+
+ /* To generate channel readers */
+ genvar i ;
+
+ /* These will eventually be external register */
+ reg [31:0] timestamp_clock ;
+ wire [7:0] txstrobe_rate [NUM_CHAN-1:0] ;
+ wire [31:0] rssi [3:0];
+ assign rssi[0] = rssi_0;
+ assign rssi[1] = rssi_1;
+ assign rssi[2] = rssi_2;
+ assign rssi[3] = rssi_3;
+
+ always @(posedge txclk)
+ if (reset)
+ timestamp_clock <= 0;
+ else
+ timestamp_clock <= timestamp_clock + 1;
+
+
+ /* Connections between tx_usb_fifo_reader and
+ cnannel/command processing blocks */
+ wire [31:0] tx_data_bus ;
+ wire [NUM_CHAN:0] chan_WR ;
+ wire [NUM_CHAN:0] chan_done ;
+
+ /* Connections between data block and the
+ FX2/TX chains */
+ wire [NUM_CHAN:0] chan_underrun;
+ wire [NUM_CHAN:0] chan_txempty;
+
+ /* Conections between tx_data_packet_fifo and
+ its reader + strobe generator */
+ wire [31:0] chan_fifodata [NUM_CHAN:0] ;
+ wire chan_pkt_waiting [NUM_CHAN:0] ;
+ wire chan_rdreq [NUM_CHAN:0] ;
+ wire chan_skip [NUM_CHAN:0] ;
+ wire chan_have_space [NUM_CHAN:0] ;
+
+ wire [14:0] debug [NUM_CHAN:0];
+
+ /* Outputs to transmit chains */
+ wire [15:0] tx_i [NUM_CHAN:0] ;
+ wire [15:0] tx_q [NUM_CHAN:0] ;
+
+ assign tx_i[NUM_CHAN] = 0;
+ assign tx_q[NUM_CHAN] = 0;
+
+ assign have_space = chan_have_space[0] & chan_have_space[1];
+ assign tx_empty = chan_txempty[0] & chan_txempty[1] ;
+
+ assign tx_i_0 = chan_txempty[0] ? 16'b0 : tx_i[0] ;
+ assign tx_q_0 = chan_txempty[0] ? 16'b0 : tx_q[0] ;
+ assign tx_i_1 = chan_txempty[1] ? 16'b0 : tx_i[1] ;
+ assign tx_q_1 = chan_txempty[1] ? 16'b0 : tx_q[1] ;
+
+ assign tx_q_2 = 16'b0 ;
+ assign tx_i_2 = 16'b0 ;
+ assign tx_q_3 = 16'b0 ;
+ assign tx_i_3 = 16'b0 ;
+ assign tx_i_3 = 16'b0 ;
+
+ assign debugbus = {have_space, txclk, WR, WR_final, chan_WR, chan_done,
+ chan_pkt_waiting[0], chan_pkt_waiting[1],
+ chan_rdreq[0], chan_rdreq[1], chan_txempty[0], chan_txempty[1]};
+
+ wire [31:0] usbdata_final;
+ wire WR_final;
+
+ tx_packer tx_usb_packer
+ (.bus_reset(bus_reset), .usbclk(usbclk), .WR_fx2(WR),
+ .usbdata(usbdata), .reset(reset), .txclk(txclk),
+ .usbdata_final(usbdata_final), .WR_final(WR_final));
+
+ channel_demux #(NUM_CHAN) channel_demuxer
+ (.usbdata_final(usbdata_final), .WR_final(WR_final),
+ .reset(reset), .txclk(txclk), .WR_channel(chan_WR),
+ .WR_done_channel(chan_done), .ram_data(tx_data_bus));
+
+ generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+ begin : generate_channel_readers
+ assign tx_underrun[i] = chan_underrun[i];
+
+ channel_ram tx_data_packet_fifo
+ (.reset(reset), .txclk(txclk), .datain(tx_data_bus),
+ .WR(chan_WR[i]), .WR_done(chan_done[i]),
+ .have_space(chan_have_space[i]), .dataout(chan_fifodata[i]),
+ .packet_waiting(chan_pkt_waiting[i]), .RD(chan_rdreq[i]),
+ .RD_done(chan_skip[i]));
+
+ chan_fifo_reader tx_chan_reader
+ (.reset(reset), .tx_clock(txclk), .tx_strobe(txstrobe),
+ .timestamp_clock(timestamp_clock), .samples_format(4'b0),
+ .tx_q(tx_q[i]), .tx_i(tx_i[i]), .underrun(chan_underrun[i]),
+ .skip(chan_skip[i]), .rdreq(chan_rdreq[i]),
+ .fifodata(chan_fifodata[i]), .pkt_waiting(chan_pkt_waiting[i]),
+ .tx_empty(chan_txempty[i]), .rssi(rssi[i]), .debug(debug[i]),
+ .threshhold(threshhold), .rssi_wait(rssi_wait));
+ end
+ endgenerate
+
+
+ channel_ram tx_cmd_packet_fifo
+ (.reset(reset), .txclk(txclk), .datain(tx_data_bus), .WR(chan_WR[NUM_CHAN]),
+ .WR_done(chan_done[NUM_CHAN]), .have_space(chan_have_space[NUM_CHAN]),
+ .dataout(chan_fifodata[NUM_CHAN]), .packet_waiting(chan_pkt_waiting[NUM_CHAN]),
+ .RD(chan_rdreq[NUM_CHAN]), .RD_done(chan_skip[NUM_CHAN]));
+
+ cmd_reader tx_cmd_reader
+ (.reset(reset), .txclk(txclk), .timestamp_clock(timestamp_clock), .skip(chan_skip[NUM_CHAN]),
+ .rdreq(chan_rdreq[NUM_CHAN]), .fifodata(chan_fifodata[NUM_CHAN]),
+ .pkt_waiting(chan_pkt_waiting[NUM_CHAN]), .rx_databus(rx_databus),
+ .rx_WR(rx_WR), .rx_WR_done(rx_WR_done), .rx_WR_enabled(rx_WR_enabled),
+ .reg_data_in(reg_data_in), .reg_data_out(reg_data_out), .reg_addr(reg_addr),
+ .reg_io_enable(reg_io_enable), .debug(debug[NUM_CHAN]), .stop(stop), .stop_time(stop_time));
+
+endmodule // tx_buffer
+
diff --git a/fpga/usrp1/inband_lib/tx_packer.v b/fpga/usrp1/inband_lib/tx_packer.v
new file mode 100644
index 000000000..2f19b21f3
--- /dev/null
+++ b/fpga/usrp1/inband_lib/tx_packer.v
@@ -0,0 +1,119 @@
+module tx_packer
+ ( //FX2 Side
+ input bus_reset,
+ input usbclk,
+ input WR_fx2,
+ input [15:0]usbdata,
+
+ // TX Side
+ input reset,
+ input txclk,
+ output reg [31:0] usbdata_final,
+ output reg WR_final);
+
+ reg [8:0] write_count;
+
+ /* Fix FX2 bug */
+ always @(posedge usbclk)
+ begin
+ if(bus_reset) // Use bus reset because this is on usbclk
+ write_count <= #1 0;
+ else if(WR_fx2 & ~write_count[8])
+ write_count <= #1 write_count + 9'd1;
+ else
+ write_count <= #1 WR_fx2 ? write_count : 9'b0;
+ end
+
+ reg WR_fx2_fixed;
+ reg [15:0]usbdata_fixed;
+
+ always @(posedge usbclk)
+ begin
+ WR_fx2_fixed <= WR_fx2 & ~write_count[8];
+ usbdata_fixed <= usbdata;
+ end
+
+ /* Used to convert 16 bits bus_data to the 32 bits wide fifo */
+ reg word_complete ;
+ reg [15:0] usbdata_delayed ;
+ reg writing ;
+ wire [31:0] usbdata_packed ;
+ wire WR_packed ;
+
+ always @(posedge usbclk)
+ begin
+ if (bus_reset)
+ begin
+ word_complete <= 0 ;
+ writing <= 0 ;
+ end
+ else if (WR_fx2_fixed)
+ begin
+ writing <= 1 ;
+ if (word_complete)
+ word_complete <= 0 ;
+ else
+ begin
+ usbdata_delayed <= usbdata_fixed ;
+ word_complete <= 1 ;
+ end
+ end
+ else
+ writing <= 0 ;
+ end
+
+ assign usbdata_packed = {usbdata_fixed, usbdata_delayed} ;
+ assign WR_packed = word_complete & writing ;
+
+ /* Make sure data are sync with usbclk */
+ reg [31:0]usbdata_usbclk;
+ reg WR_usbclk;
+
+ always @(posedge usbclk)
+ begin
+ if (WR_packed)
+ usbdata_usbclk <= usbdata_packed;
+ WR_usbclk <= WR_packed;
+ end
+
+ /* Cross clock boundaries */
+ reg [31:0] usbdata_tx ;
+ reg WR_tx;
+ reg WR_1;
+ reg WR_2;
+
+ always @(posedge txclk) usbdata_tx <= usbdata_usbclk;
+
+ always @(posedge txclk)
+ if (reset)
+ WR_1 <= 0;
+ else
+ WR_1 <= WR_usbclk;
+
+ always @(posedge txclk)
+ if (reset)
+ WR_2 <= 0;
+ else
+ WR_2 <= WR_1;
+
+ always @(posedge txclk)
+ begin
+ if (reset)
+ WR_tx <= 0;
+ else
+ WR_tx <= WR_1 & ~WR_2;
+ end
+
+ always @(posedge txclk)
+ begin
+ if (reset)
+ WR_final <= 0;
+ else
+ begin
+ WR_final <= WR_tx;
+ if (WR_tx)
+ usbdata_final <= usbdata_tx;
+ end
+ end
+
+endmodule
diff --git a/fpga/usrp1/inband_lib/usb_packet_fifo.v b/fpga/usrp1/inband_lib/usb_packet_fifo.v
new file mode 100755
index 000000000..c416e2bdb
--- /dev/null
+++ b/fpga/usrp1/inband_lib/usb_packet_fifo.v
@@ -0,0 +1,112 @@
+module usb_packet_fifo
+ ( input reset,
+ input clock_in,
+ input clock_out,
+ input [15:0]ram_data_in,
+ input write_enable,
+ output reg [15:0]ram_data_out,
+ output reg pkt_waiting,
+ output reg have_space,
+ input read_enable,
+ input skip_packet ) ;
+
+ /* Some parameters for usage later on */
+ parameter DATA_WIDTH = 16 ;
+ parameter NUM_PACKETS = 4 ;
+
+ /* Create the RAM here */
+ reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
+
+ /* Create the address signals */
+ reg [7-2+NUM_PACKETS:0] usb_ram_ain ;
+ reg [7:0] usb_ram_offset ;
+ reg [1:0] usb_ram_packet ;
+
+ wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
+ reg isfull;
+
+ assign usb_ram_aout = {usb_ram_packet,usb_ram_offset} ;
+
+ // Check if there is one full packet to process
+ always @(usb_ram_ain, usb_ram_aout)
+ begin
+ if (reset)
+ pkt_waiting <= 0;
+ else if (usb_ram_ain == usb_ram_aout)
+ pkt_waiting <= isfull;
+ else if (usb_ram_ain > usb_ram_aout)
+ pkt_waiting <= (usb_ram_ain - usb_ram_aout) >= 256;
+ else
+ pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
+ end
+
+ // Check if there is room
+ always @(usb_ram_ain, usb_ram_aout)
+ begin
+ if (reset)
+ have_space <= 1;
+ else if (usb_ram_ain == usb_ram_aout)
+ have_space <= ~isfull;
+ else if (usb_ram_ain > usb_ram_aout)
+ have_space <= (usb_ram_ain - usb_ram_aout) <= 256 * (NUM_PACKETS - 1);
+ else
+ have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
+ end
+
+ /* RAM Write Address process */
+ always @(posedge clock_in)
+ begin
+ if( reset )
+ usb_ram_ain <= 0 ;
+ else
+ if( write_enable )
+ begin
+ usb_ram_ain <= usb_ram_ain + 1 ;
+ if (usb_ram_ain + 1 == usb_ram_aout)
+ isfull <= 1;
+ end
+ end
+
+ /* RAM Writing process */
+ always @(posedge clock_in)
+ begin
+ if( write_enable )
+ begin
+ usb_ram[usb_ram_ain] <= ram_data_in ;
+ end
+ end
+
+ /* RAM Read Address process */
+ always @(posedge clock_out)
+ begin
+ if( reset )
+ begin
+ usb_ram_packet <= 0 ;
+ usb_ram_offset <= 0 ;
+ isfull <= 0;
+ end
+ else
+ if( skip_packet )
+ begin
+ usb_ram_packet <= usb_ram_packet + 1 ;
+ usb_ram_offset <= 0 ;
+ end
+ else if(read_enable)
+ if( usb_ram_offset == 8'b11111111 )
+ begin
+ usb_ram_offset <= 0 ;
+ usb_ram_packet <= usb_ram_packet + 1 ;
+ end
+ else
+ usb_ram_offset <= usb_ram_offset + 1 ;
+ if (usb_ram_ain == usb_ram_aout)
+ isfull <= 0;
+ end
+
+ /* RAM Reading Process */
+ always @(posedge clock_out)
+ begin
+ ram_data_out <= usb_ram[usb_ram_aout] ;
+ end
+
+endmodule \ No newline at end of file