diff options
author | eb <eb@221aa14e-8319-0410-a670-987f0aec2ac5> | 2007-05-02 04:08:47 +0000 |
---|---|---|
committer | eb <eb@221aa14e-8319-0410-a670-987f0aec2ac5> | 2007-05-02 04:08:47 +0000 |
commit | b535098017d3df071b031bd15452a7bba53aab14 (patch) | |
tree | 24b141edd2f7d57562ae2e2ad05502b7852ad06f /inband_lib | |
parent | 5a17f48e7374466b10787ef2721166b1bb862cf1 (diff) | |
download | uhd-b535098017d3df071b031bd15452a7bba53aab14.tar.gz uhd-b535098017d3df071b031bd15452a7bba53aab14.tar.bz2 uhd-b535098017d3df071b031bd15452a7bba53aab14.zip |
Merged features/inband -r4812:5218 into trunk. This group of changes includes:
* working stand-alone mblock code
* work-in-progress on usrp inband signaling
usrp now depends on mblock, and guile is a dependency.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5221 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'inband_lib')
-rwxr-xr-x | inband_lib/chan_fifo_reader.v | 197 | ||||
-rwxr-xr-x | inband_lib/data_packet_fifo.v | 128 | ||||
-rwxr-xr-x | inband_lib/tx_buffer_inband.v | 183 | ||||
-rwxr-xr-x | inband_lib/usb_fifo_reader.v | 135 | ||||
-rwxr-xr-x | inband_lib/usb_packet_fifo.v | 112 | ||||
-rwxr-xr-x | inband_lib/usb_packet_fifo2.v | 119 |
6 files changed, 874 insertions, 0 deletions
diff --git a/inband_lib/chan_fifo_reader.v b/inband_lib/chan_fifo_reader.v new file mode 100755 index 000000000..2b3178da7 --- /dev/null +++ b/inband_lib/chan_fifo_reader.v @@ -0,0 +1,197 @@ +module chan_fifo_reader + ( input reset, + input tx_clock, + input tx_strobe, + input [31:0]adc_clock, + input [3:0] samples_format, + input [15:0] fifodata, + input pkt_waiting, + output reg rdreq, + output reg skip, + output reg [15:0]tx_q, + output reg [15:0]tx_i, + output reg overrun, + output reg underrun) ; + + // Should not be needed if adc clock rate < tx clock rate + `define JITTER 5 + + //Samples format + // 16 bits interleaved complex samples + `define QI16 4'b0 + + // States + `define IDLE 4'd0 + `define READ 4'd1 + `define HEADER1 4'd2 + `define HEADER2 4'd3 + `define TIMESTAMP1 4'd4 + `define TIMESTAMP2 4'd5 + `define WAIT 4'd6 + `define WAITSTROBE 4'd7 + `define SENDWAIT 4'd8 + `define SEND 4'd9 + `define FEED 4'd10 + `define DISCARD 4'd11 + + // State registers + reg[3:0] reader_state; + reg[3:0] reader_next_state; + + //Variables + reg[8:0] payload_len; + reg[8:0] read_len; + reg[31:0] timestamp; + reg burst; + reg qsample; + always @(posedge tx_clock) + begin + if (reset) + begin + reader_state <= `IDLE; + reader_next_state <= `IDLE; + rdreq <= 0; + skip <= 0; + overrun <= 0; + underrun <= 0; + burst <= 0; + qsample <= 1; + end + else + begin + reader_state = reader_next_state; + case (reader_state) + `IDLE: + begin + if (pkt_waiting == 1) + begin + reader_next_state <= `READ; + rdreq <= 1; + underrun <= 0; + end + else if (burst == 1) + underrun <= 1; + end + + // Just wait for the fifo data to arrive + `READ: + begin + reader_next_state <= `HEADER1; + end + + // First part of the header + `HEADER1: + begin + reader_next_state <= `HEADER2; + + //Check Start burst flag + if (fifodata[3] == 1) + burst <= 1; + + if (fifodata[4] == 1) + burst <= 0; + end + + // Read payload length + `HEADER2: + begin + payload_len <= (fifodata & 16'h1FF); + read_len <= 9'd0; + reader_next_state <= `TIMESTAMP1; + end + + `TIMESTAMP1: + begin + timestamp <= {fifodata, 16'b0}; + rdreq <= 0; + reader_next_state <= `TIMESTAMP2; + end + + `TIMESTAMP2: + begin + timestamp <= timestamp + fifodata; + reader_next_state <= `WAIT; + end + + // Decide if we wait, send or discard samples + `WAIT: + begin + // Wait a little bit more + if (timestamp > adc_clock + `JITTER) + reader_next_state <= `WAIT; + // Let's send it + else if ((timestamp < adc_clock + `JITTER + && timestamp > adc_clock) + || timestamp == 32'hFFFFFFFF) + begin + reader_next_state <= `WAITSTROBE; + end + // Outdated + else if (timestamp < adc_clock) + begin + reader_next_state <= `DISCARD; + skip <= 1; + end + end + + // Wait for the transmit chain to be ready + `WAITSTROBE: + begin + // If end of payload... + if (read_len == payload_len) + begin + reader_next_state <= `DISCARD; + skip <= (payload_len < 508); + end + + if (tx_strobe == 1) + reader_next_state <= `SENDWAIT; + end + + `SENDWAIT: + begin + rdreq <= 1; + reader_next_state <= `SEND; + end + + // Send the samples to the tx_chain + `SEND: + begin + reader_next_state <= `WAITSTROBE; + rdreq <= 0; + read_len <= read_len + 2; + case(samples_format) + `QI16: + begin + tx_q <= qsample ? fifodata : 16'bZ; + tx_i <= ~qsample ? fifodata : 16'bZ; + qsample <= ~ qsample; + end + default: + begin + // Assume 16 bits complex samples by default + $display ("Error unknown samples format"); + tx_q <= qsample ? fifodata : 16'bZ; + tx_i <= ~qsample ? fifodata : 16'bZ; + qsample <= ~ qsample; + end + endcase + end + + `DISCARD: + begin + skip <= 0; + reader_next_state <= `IDLE; + end + + default: + begin + $display ("Error unknown state"); + reader_state <= `IDLE; + reader_next_state <= `IDLE; + end + endcase + end + end + +endmodule
\ No newline at end of file diff --git a/inband_lib/data_packet_fifo.v b/inband_lib/data_packet_fifo.v new file mode 100755 index 000000000..5b37b14ea --- /dev/null +++ b/inband_lib/data_packet_fifo.v @@ -0,0 +1,128 @@ +module data_packet_fifo + ( input reset, + input clock, + input [15:0]ram_data_in, + input write_enable, + output reg have_space, + output reg [15:0]ram_data_out, + output reg pkt_waiting, + input read_enable, + input pkt_complete, + 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:0] usb_ram_offset_out ; + reg [1:0] usb_ram_packet_out ; + reg [7:0] usb_ram_offset_in ; + reg [1:0] usb_ram_packet_in ; + + wire [7-2+NUM_PACKETS:0] usb_ram_aout ; + wire [7-2+NUM_PACKETS:0] usb_ram_ain ; + reg isfull; + + assign usb_ram_aout = {usb_ram_packet_out, usb_ram_offset_out} ; + assign usb_ram_ain = {usb_ram_packet_in, usb_ram_offset_in} ; + + // 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 <= 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) + begin + if( reset ) + begin + usb_ram_offset_in <= 0 ; + usb_ram_packet_in <= 0 ; + end + else + if( pkt_complete ) + begin + usb_ram_packet_in <= usb_ram_packet_in + 1; + usb_ram_offset_in <= 0; + end + else if( write_enable ) + begin + if (usb_ram_offset_in == 8'b11111111) + begin + usb_ram_offset_in <= 0; + usb_ram_packet_in <= usb_ram_packet_in + 1; + end + else + usb_ram_offset_in <= usb_ram_offset_in + 1 ; + if (usb_ram_ain + 1 == usb_ram_aout) + isfull <= 1; + end + end + + /* RAM Writing process */ + always @(posedge clock) + begin + if( write_enable ) + begin + usb_ram[usb_ram_ain] <= ram_data_in ; + end + end + + /* RAM Read Address process */ + always @(posedge clock) + begin + if( reset ) + begin + usb_ram_packet_out <= 0 ; + usb_ram_offset_out <= 0 ; + isfull <= 0; + end + else + if( skip_packet ) + begin + usb_ram_packet_out <= usb_ram_packet_out + 1 ; + usb_ram_offset_out <= 0 ; + end + else if(read_enable) begin + if( usb_ram_offset_out == 8'b11111111 ) + begin + usb_ram_offset_out <= 0 ; + usb_ram_packet_out <= usb_ram_packet_out + 1 ; + end + else + usb_ram_offset_out <= usb_ram_offset_out + 1 ; + end + if (usb_ram_ain == usb_ram_aout) + isfull <= 0; + end + + /* RAM Reading Process */ + always @(posedge clock) + begin + ram_data_out <= usb_ram[usb_ram_aout] ; + end + +endmodule diff --git a/inband_lib/tx_buffer_inband.v b/inband_lib/tx_buffer_inband.v new file mode 100755 index 000000000..56c07807a --- /dev/null +++ b/inband_lib/tx_buffer_inband.v @@ -0,0 +1,183 @@ +module tx_buffer_inband + ( input usbclk, + input bus_reset, // Used here for the 257-Hack to fix the FX2 bug + input reset, // standard DSP-side reset + input [15:0] usbdata, + input wire WR, + output wire have_space, + output reg tx_underrun, + input wire [3:0] channels, + output [15:0] tx_i_0, + output [15:0] tx_q_0, + output [15:0] tx_i_1, + output [15:0] tx_q_1, + //NOT USED + output reg [15:0] tx_i_2, + output reg [15:0] tx_q_2, + output reg [15:0] tx_i_3, + output reg [15:0] tx_q_3, + input txclk, + input txstrobe, + input clear_status, + output wire tx_empty, + output [11:0] debugbus + ); + + wire [15:0] tx_data_bus; + + wire WR_chan_0; + wire chan_0_done; + wire OR0; + wire UR0; + + wire WR_chan_1; + wire chan_1_done; + wire OR1; + wire UR1; + + // NOT USED yet + wire WR_cmd; + wire cmd_done; + + //EXTERNAL REGISTER + //TODO: increment it + reg [31:0] time_counter; + reg [7:0] txstrobe_rate_0; + reg [7:0] txstrobe_rate_1; + + + //Usb block + wire [15:0] tupf_fifodata; + wire tupf_pkt_waiting; + wire tupf_rdreq; + wire tupf_skip; + wire tupf_have_space; + + usb_packet_fifo2 tx_usb_packet_fifo + ( .reset (reset), + .usb_clock (usbclk), + .fpga_clock (txclk), + .write_data (usbdata), + .write_enable (WR), + .read_data (tupf_fifodata), + .pkt_waiting (tupf_pkt_waiting), + .read_enable (tupf_rdreq), + .skip_packet (tupf_skip), + .have_space (tupf_have_space), + .tx_empty (tx_empty) + ); + + usb_fifo_reader tx_usb_packet_reader ( + .reset(reset), + .tx_clock(txclk), + .tx_data_bus(tx_data_bus), + .WR_chan_0(WR_chan_0), + .WR_chan_1(WR_chan_1), + .WR_cmd(WR_cmd), + .chan_0_done(chan_0_done), + .chan_1_done(chan_1_done), + .cmd_done(cmd_done), + .rdreq(tupf_rdreq), + .skip(tupf_skip), + .pkt_waiting(tupf_pkt_waiting), + .fifodata(tupf_fifodata) + ); + + + //Channel 0 block + wire [15:0] tdpf_fifodata_0; + wire tdpf_pkt_waiting_0; + wire tdpf_rdreq_0; + wire tdpf_skip_0; + wire tdpf_have_space_0; + wire txstrobe_chan_0; + + data_packet_fifo tx_data_packet_fifo_0 + ( .reset(reset), + .clock(txclk), + .ram_data_in(tx_data_bus), + .write_enable(WR_chan_0), + .ram_data_out(tdpf_fifodata_0), + .pkt_waiting(tdpf_pkt_waiting_0), + .read_enable(tdpf_rdreq_0), + .pkt_complete(chan_0_done), + .skip_packet(tdpf_skip_0), + .have_space(tdpf_have_space_0) + ); + + strobe_gen strobe_gen_0 + ( .clock(txclk), + .reset(reset), + .enable(1'b1), + .rate(txstrobe_rate_0), + .strobe_in(txstrobe), + .strobe(txstrobe_chan_0) + ); + + chan_fifo_reader tx_chan_0_reader ( + .reset(reset), + .tx_clock(txclk), + .tx_strobe(txstrobe), + //.tx_strobe(txstrobe_chan_0), + .adc_clock(time_counter), + .samples_format(4'b0), + .tx_q(tx_q_0), + .tx_i(tx_i_0), + .overrun(OR0), + .underrun(UR0), + .skip(tdpf_skip_0), + .rdreq(tdpf_rdreq_0), + .fifodata(tdpf_fifodata_0), + .pkt_waiting(tdpf_pkt_waiting_0) + ); + + + //Channel 1 block + wire [15:0] tdpf_fifodata_1; + wire tdpf_pkt_waiting_1; + wire tdpf_rdreq_1; + wire tdpf_skip_1; + wire tdpf_have_space_1; + wire txstrobe_chan_1; + + data_packet_fifo tx_data_packet_fifo_1 + ( .reset(reset), + .clock(txclk), + .ram_data_in(tx_data_bus), + .write_enable(WR_chan_1), + .ram_data_out(tdpf_fifodata_1), + .pkt_waiting(tdpf_pkt_waiting_1), + .read_enable(tdpf_rdreq_1), + .pkt_complete(chan_1_done), + .skip_packet(tdpf_skip_1), + .have_space(tdpf_have_space_1) + ); + + strobe_gen strobe_gen_1 + ( .clock(txclk), + .reset(reset), + .enable(1'b1), + .rate(txstrobe_rate_1), + .strobe_in(txstrobe), + .strobe(txstrobe_chan_1) + ); + + chan_fifo_reader tx_chan_1_reader ( + .reset(reset), + .tx_clock(txclk), + .tx_strobe(txstrobe), + //.tx_strobe(txstrobe_chan_1), + .adc_clock(time_counter), + .samples_format(4'b0), + .tx_q(tx_q_1), + .tx_i(tx_i_1), + .overrun(OR1), + .underrun(UR1), + .skip(tdpf_skip_1), + .rdreq(tdpf_rdreq_1), + .fifodata(tdpf_fifodata_1), + .pkt_waiting(tdpf_pkt_waiting_1) + ); + +endmodule // tx_buffer + diff --git a/inband_lib/usb_fifo_reader.v b/inband_lib/usb_fifo_reader.v new file mode 100755 index 000000000..170c70fd4 --- /dev/null +++ b/inband_lib/usb_fifo_reader.v @@ -0,0 +1,135 @@ +module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset, + rdreq, skip, done_chan, WR_chan, tx_data_bus); + + /* Module parameters */ + parameter NUM_CHAN = 2 ; + parameter WIDTH = 32 ; + + input wire tx_clock ; + input wire reset ; + input wire [WIDTH-1:0] fifodata ; + input wire pkt_waiting ; + output reg rdreq ; + output reg skip ; + output reg [NUM_CHAN:0] done_chan ; + output reg [NUM_CHAN:0] WR_chan ; + output reg [WIDTH-1:0] tx_data_bus ; + + + + /* States definition */ + `define IDLE 3'd0 + `define WAIT 3'd1 + `define READ_HEADER 3'd2 + `define FORWARD_DATA 3'd3 + `define SKIP_REST 3'd4 + + /* Channel Ids */ + `define TXCHAN0 5'h0 + `define TXCHAN1 5'h1 + `define TXCMD 5'h1F + + /* Local registers */ + reg [2:0] reader_state ; + reg [2:0] reader_next_state ; + reg [4:0] channel ; + reg [8:0] pkt_length ; + reg [8:0] read_length ; + + /* State Machine */ + always @(posedge tx_clock) + begin + if (reset) + begin + reader_state <= `IDLE ; + reader_next_state <= `IDLE ; + rdreq <= 0 ; + skip <= 0 ; + WR_chan <= {NUM_CHAN+1{1'b0}} ; + done_chan <= {NUM_CHAN+1{1'b0}} ; + end + else + begin + reader_state = reader_next_state ; + + case(reader_state) + `IDLE: + begin + reader_next_state <= pkt_waiting ? `WAIT : `IDLE ; + rdreq <= pkt_waiting ; + end + + /* Wait for the fifo's data to show up */ + `WAIT: + begin + reader_next_state <= `READ_HEADER ; + end + + `READ_HEADER: + begin + reader_next_state <= `FORWARD_DATA ; + + /* Read header fields */ + channel <= (fifodata & 32'h1F0000) ; + pkt_length <= (fifodata & 16'h1FF) + 4 ; + read_length <= 9'd0 ; + + /* Forward data */ + case (channel) + `TXCHAN0: WR_chan[0] <= 1 ; + `TXCHAN1: WR_chan[1] <= 1 ; + `TXCMD: WR_chan[2] <= 1 ; + default: WR_chan <= 1 ; + endcase + tx_data_bus <= fifodata ; + end + + `FORWARD_DATA: + begin + read_length <= read_length + 4 ; + + // If end of payload... + if (read_length == pkt_length) + begin + reader_next_state <= `SKIP_REST ; + /* If the packet is 512 bytes, don't skip */ + skip <= pkt_length < 506 ; + + /* Data pushing done */ + WR_chan <= {NUM_CHAN+1{1'b0}} ; + + /* Notify next block */ + case (channel) + `TXCHAN0: done_chan[0] <= 1 ; + `TXCHAN1: done_chan[1] <= 1 ; + `TXCMD: done_chan[2] <= 1 ; + default: done_chan[0] <= 1 ; + endcase + end + else if (read_length == pkt_length - 4) + rdreq <= 0 ; + + /* Forward data */ + tx_data_bus <= fifodata ; + end + + `SKIP_REST: + begin + reader_next_state <= pkt_waiting ? `READ_HEADER : `IDLE ; + done_chan <= {NUM_CHAN+1{1'b0}} ; + rdreq <= pkt_waiting ; + skip <= 0 ; + end + + default: + begin + reader_state <= `IDLE; + reader_next_state <= `IDLE; + end + endcase + end + end +endmodule + + +
\ No newline at end of file diff --git a/inband_lib/usb_packet_fifo.v b/inband_lib/usb_packet_fifo.v new file mode 100755 index 000000000..c416e2bdb --- /dev/null +++ b/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 diff --git a/inband_lib/usb_packet_fifo2.v b/inband_lib/usb_packet_fifo2.v new file mode 100755 index 000000000..d815e4e37 --- /dev/null +++ b/inband_lib/usb_packet_fifo2.v @@ -0,0 +1,119 @@ +`default_nettype none + +module usb_packet_fifo2(reset, usb_clock, fpga_clock, write_enable, write_data, + read_enable, skip_packet, read_data, have_space, pkt_waiting, tx_empty) ; + + /* Module parameters */ + parameter LOG2_N = 2 ; + parameter BUS_WIDTH = 16 ; + parameter FIFO_WIDTH = 32 ; + + input wire reset; + input wire usb_clock ; + input wire fpga_clock ; + input wire write_enable ; + input wire [BUS_WIDTH-1:0] write_data ; + input wire read_enable ; + input wire skip_packet ; + output wire [FIFO_WIDTH-1:0] read_data ; + output wire have_space ; + output wire pkt_waiting ; + output wire tx_empty; + + + /* Variable for generate statement */ + genvar i ; + + /* Local wires for FIFO connections */ + wire [2**LOG2_N-1:0] fifo_resets ; + reg [2**LOG2_N-1:0] fifo_we ; + wire [2**LOG2_N-1:0] fifo_re ; + reg [FIFO_WIDTH-1:0] fifo_wdata[2**LOG2_N-1:0] ; + wire [FIFO_WIDTH-1:0] fifo_rdata[2**LOG2_N-1:0] ; + wire [2**LOG2_N-1:0] fifo_rempty ; + wire [2**LOG2_N-1:0] fifo_rfull ; + wire [2**LOG2_N-1:0] fifo_wempty ; + wire [2**LOG2_N-1:0] fifo_wfull ; + + /* FIFO Select for read and write ports */ + reg [LOG2_N-1:0] fifo_rselect ; + reg [LOG2_N-1:0] fifo_wselect ; + + /* Used to convert 16 bits usbdata to the 32 bits wide fifo */ + reg word_complete ; + reg [BUS_WIDTH-1:0] write_data_delayed ; + + /* Assign have_space to empty flag of currently selected write FIFO */ + assign have_space = fifo_wempty[fifo_wselect] ; + + /* Assign pkt_waiting to full flag of currently selected read FIFO */ + assign pkt_waiting = fifo_rfull[fifo_rselect] ; + + /* Assign the read_data to the output of the currently selected FIFO */ + assign read_data = fifo_rdata[fifo_rselect] ; + + /* Figure out if we're all empty */ + assign tx_empty = !(~fifo_rempty) ; + + /* Increment fifo_rselect here */ + always @(posedge fpga_clock) + begin + if (reset) + fifo_rselect <= {2**LOG2_N{1'b0}} ; + + if (fifo_rempty[fifo_rselect]) + fifo_rselect <= fifo_rselect + 1 ; + + if (skip_packet) + fifo_rselect <= fifo_rselect + 1 ; + end + + /* Increment fifo_wselect and pack data into 32 bits block */ + always @(posedge usb_clock, reset) + begin + if (reset) + begin + fifo_wselect <= {2**LOG2_N{1'b0}} ; + word_complete <= 0; + end + + if (fifo_wfull[fifo_wselect]) + fifo_wselect <= fifo_wselect + 1 ; + + if (write_enable) + begin + word_complete <= ~word_complete ; + + if (word_complete) + fifo_wdata[fifo_wselect] <= {write_data_delayed, write_data} ; + else + write_data_delayed <= write_data ; + + /* Avoid to continue to write in the previous fifo when we have + just swichted to the next one */ + fifo_we[fifo_wselect-1] <= 0 ; + + fifo_we[fifo_wselect] <= write_enable & word_complete ; + end + end + + /* Generate all the single packet FIFOs */ + generate + for( i = 0 ; i < 2**LOG2_N ; i = i + 1 ) + begin : generate_single_packet_fifos + assign fifo_re[i] = (fifo_rselect == i) ? read_enable : 1'b0 ; + assign fifo_resets[i] = (fifo_rselect == i) ? skip_packet : 1'b0 ; + fifo_512 single_packet_fifo(.wrclk ( usb_clock ), + .rdclk ( fpga_clock ), + .aclr ( fifo_resets[i] ), + .wrreq ( fifo_we[i] ), + .data ( fifo_wdata[i] ), + .rdreq ( fifo_re[i] ), + .q ( fifo_rdata[i] ), + .rdfull ( fifo_rfull[i] ), + .rdempty( fifo_rempty[i] ), + .wrfull ( fifo_wfull[i] ), + .wrempty( fifo_wempty[i] ) ) ; + end + endgenerate +endmodule
\ No newline at end of file |