| [27] | 1 | module usb_fifo | 
|---|
|  | 2 | ( | 
|---|
|  | 3 | input   wire                    usb_clk, | 
|---|
|  | 4 | inout   wire    [7:0]   usb_data, | 
|---|
|  | 5 | input   wire                    usb_full, usb_empty, | 
|---|
|  | 6 | output  wire                    usb_wrreq, usb_rdreq, usb_rden, usb_pktend, | 
|---|
|  | 7 | output  wire    [1:0]   usb_addr, | 
|---|
|  | 8 |  | 
|---|
|  | 9 | input   wire                    clk, aclr, | 
|---|
|  | 10 | input   wire                    tx_wrreq, rx_rdreq, | 
|---|
|  | 11 | input   wire    [7:0]   tx_data, | 
|---|
|  | 12 | output  wire                    tx_full, rx_empty, | 
|---|
| [36] | 13 | output  wire    [7:0]   rx_q | 
|---|
| [27] | 14 | ); | 
|---|
|  | 15 |  | 
|---|
| [33] | 16 | wire                    int_rx_full, int_tx_empty; | 
|---|
| [36] | 17 | wire                    rx_ready, tx_ready; | 
|---|
| [33] | 18 | wire                    int_rdreq, int_wrreq, int_pktend; | 
|---|
|  | 19 | reg                             is_rx_addr_ok; | 
|---|
| [30] | 20 | reg             [8:0]   byte_counter; | 
|---|
|  | 21 | reg             [4:0]   idle_counter; | 
|---|
| [27] | 22 |  | 
|---|
| [33] | 23 | wire    [7:0]   int_rx_data = usb_data; | 
|---|
|  | 24 | wire    [7:0]   int_tx_q; | 
|---|
| [31] | 25 |  | 
|---|
| [45] | 26 | dcfifo #( | 
|---|
|  | 27 | .intended_device_family("Cyclone III"), | 
|---|
|  | 28 | .lpm_numwords(16), | 
|---|
|  | 29 | .lpm_showahead("ON"), | 
|---|
|  | 30 | .lpm_type("dcfifo"), | 
|---|
|  | 31 | .lpm_width(8), | 
|---|
|  | 32 | .lpm_widthu(4), | 
|---|
|  | 33 | .rdsync_delaypipe(4), | 
|---|
|  | 34 | .wrsync_delaypipe(4), | 
|---|
|  | 35 | .overflow_checking("ON"), | 
|---|
|  | 36 | .underflow_checking("ON"), | 
|---|
|  | 37 | .use_eab("OFF"), | 
|---|
|  | 38 | .write_aclr_synch("OFF")) fifo_tx ( | 
|---|
| [27] | 39 | .aclr(aclr), | 
|---|
|  | 40 | .data(tx_data), | 
|---|
|  | 41 | .rdclk(usb_clk), | 
|---|
| [31] | 42 | .rdreq(int_wrreq), | 
|---|
| [27] | 43 | .wrclk(clk), | 
|---|
|  | 44 | .wrreq(tx_wrreq), | 
|---|
| [33] | 45 | .q(int_tx_q), | 
|---|
|  | 46 | .rdempty(int_tx_empty), | 
|---|
| [45] | 47 | .wrfull(tx_full), | 
|---|
|  | 48 | .rdfull(), | 
|---|
|  | 49 | .rdusedw(), | 
|---|
|  | 50 | .wrempty(), | 
|---|
|  | 51 | .wrusedw()); | 
|---|
| [27] | 52 |  | 
|---|
| [45] | 53 | dcfifo #( | 
|---|
|  | 54 | .intended_device_family("Cyclone III"), | 
|---|
|  | 55 | .lpm_numwords(16), | 
|---|
|  | 56 | .lpm_showahead("ON"), | 
|---|
|  | 57 | .lpm_type("dcfifo"), | 
|---|
|  | 58 | .lpm_width(8), | 
|---|
|  | 59 | .lpm_widthu(4), | 
|---|
|  | 60 | .rdsync_delaypipe(4), | 
|---|
|  | 61 | .wrsync_delaypipe(4), | 
|---|
|  | 62 | .overflow_checking("ON"), | 
|---|
|  | 63 | .underflow_checking("ON"), | 
|---|
|  | 64 | .use_eab("OFF"), | 
|---|
|  | 65 | .write_aclr_synch("OFF")) fifo_rx ( | 
|---|
| [27] | 66 | .aclr(aclr), | 
|---|
| [33] | 67 | .data(int_rx_data), | 
|---|
| [27] | 68 | .rdclk(clk), | 
|---|
|  | 69 | .rdreq(rx_rdreq), | 
|---|
|  | 70 | .wrclk(usb_clk), | 
|---|
| [31] | 71 | .wrreq(int_rdreq), | 
|---|
| [33] | 72 | .q(rx_q), | 
|---|
| [27] | 73 | .rdempty(rx_empty), | 
|---|
| [45] | 74 | .wrfull(int_rx_full), | 
|---|
|  | 75 | .rdfull(), | 
|---|
|  | 76 | .rdusedw(), | 
|---|
|  | 77 | .wrempty(), | 
|---|
|  | 78 | .wrusedw()); | 
|---|
| [33] | 79 |  | 
|---|
|  | 80 | assign  rx_ready = (~usb_empty) & (~int_rx_full) & (~int_pktend); | 
|---|
|  | 81 | assign  tx_ready = (~rx_ready) & (~usb_full) & (~int_tx_empty) & (~int_pktend); | 
|---|
| [31] | 82 |  | 
|---|
| [33] | 83 | assign  int_rdreq = (rx_ready) & (is_rx_addr_ok); | 
|---|
|  | 84 | assign  int_wrreq = (tx_ready) & (~is_rx_addr_ok); | 
|---|
|  | 85 |  | 
|---|
|  | 86 | assign  int_pktend = (&idle_counter); | 
|---|
|  | 87 |  | 
|---|
| [30] | 88 | always @ (posedge usb_clk) | 
|---|
| [27] | 89 | begin | 
|---|
| [33] | 90 | // respect 1 clock delay between fifo selection | 
|---|
|  | 91 | // and data transfer operations | 
|---|
|  | 92 | is_rx_addr_ok <= rx_ready; | 
|---|
|  | 93 |  | 
|---|
|  | 94 | // assert pktend if buffer contains unsent data | 
|---|
|  | 95 | // and fifo_tx_unit stays empty for more than 30 clocks | 
|---|
|  | 96 | if (int_pktend) | 
|---|
| [30] | 97 | begin | 
|---|
|  | 98 | byte_counter <= 9'd0; | 
|---|
|  | 99 | idle_counter <= 5'd0; | 
|---|
|  | 100 | end | 
|---|
| [33] | 101 | else if (int_wrreq) | 
|---|
| [30] | 102 | begin | 
|---|
|  | 103 | byte_counter <= byte_counter + 9'd1; | 
|---|
|  | 104 | idle_counter <= 5'd0; | 
|---|
|  | 105 | end | 
|---|
| [33] | 106 | else if ((|byte_counter) & (int_tx_empty) & (~rx_ready)) | 
|---|
| [30] | 107 | begin | 
|---|
|  | 108 | byte_counter <= byte_counter; | 
|---|
|  | 109 | idle_counter <= idle_counter + 5'd1; | 
|---|
|  | 110 | end | 
|---|
| [33] | 111 |  | 
|---|
| [27] | 112 | end | 
|---|
|  | 113 |  | 
|---|
| [33] | 114 | assign  usb_pktend = int_pktend; | 
|---|
| [31] | 115 | assign  usb_rdreq = int_rdreq; | 
|---|
|  | 116 | assign  usb_wrreq = int_wrreq; | 
|---|
| [33] | 117 | assign  usb_rden = int_rdreq; | 
|---|
|  | 118 | assign  usb_addr = {1'b1, ~rx_ready}; | 
|---|
|  | 119 | assign  usb_data = int_wrreq ? int_tx_q : 8'bz; | 
|---|
| [27] | 120 |  | 
|---|
| [58] | 121 | endmodule | 
|---|