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