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,
|
---|
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("ON"),
|
---|
38 | .write_aclr_synch("OFF")) fifo_tx (
|
---|
39 | .aclr(aclr),
|
---|
40 | .data(tx_data),
|
---|
41 | .rdclk(usb_clk),
|
---|
42 | .rdreq(int_wrreq),
|
---|
43 | .wrclk(clk),
|
---|
44 | .wrreq(tx_wrreq),
|
---|
45 | .q(int_tx_q),
|
---|
46 | .rdempty(int_tx_empty),
|
---|
47 | .wrfull(tx_full),
|
---|
48 | .rdfull(),
|
---|
49 | .rdusedw(),
|
---|
50 | .wrempty(),
|
---|
51 | .wrusedw());
|
---|
52 |
|
---|
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("ON"),
|
---|
65 | .write_aclr_synch("OFF")) fifo_rx (
|
---|
66 | .aclr(aclr),
|
---|
67 | .data(int_rx_data),
|
---|
68 | .rdclk(clk),
|
---|
69 | .rdreq(rx_rdreq),
|
---|
70 | .wrclk(usb_clk),
|
---|
71 | .wrreq(int_rdreq),
|
---|
72 | .q(rx_q),
|
---|
73 | .rdempty(rx_empty),
|
---|
74 | .wrfull(int_rx_full),
|
---|
75 | .rdfull(),
|
---|
76 | .rdusedw(),
|
---|
77 | .wrempty(),
|
---|
78 | .wrusedw());
|
---|
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);
|
---|
82 |
|
---|
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 |
|
---|
88 | always @ (posedge usb_clk)
|
---|
89 | begin
|
---|
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)
|
---|
97 | begin
|
---|
98 | byte_counter <= 9'd0;
|
---|
99 | idle_counter <= 5'd0;
|
---|
100 | end
|
---|
101 | else if (int_wrreq)
|
---|
102 | begin
|
---|
103 | byte_counter <= byte_counter + 9'd1;
|
---|
104 | idle_counter <= 5'd0;
|
---|
105 | end
|
---|
106 | else if ((|byte_counter) & (int_tx_empty) & (~rx_ready))
|
---|
107 | begin
|
---|
108 | byte_counter <= byte_counter;
|
---|
109 | idle_counter <= idle_counter + 5'd1;
|
---|
110 | end
|
---|
111 |
|
---|
112 | end
|
---|
113 |
|
---|
114 | assign usb_pktend = int_pktend;
|
---|
115 | assign usb_rdreq = int_rdreq;
|
---|
116 | assign usb_wrreq = int_wrreq;
|
---|
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;
|
---|
120 |
|
---|
121 | endmodule
|
---|