OpenCores
URL https://opencores.org/ocsvn/usb_fpga_2_14/usb_fpga_2_14/trunk

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [default/] [fpga-fx3/] [ezusb_io.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
/*%
2
   Common communication interface of default firmwares
3
   Copyright (C) 2009-2017 ZTEX GmbH.
4
   http://www.ztex.de
5
 
6
   Copyright and related rights are licensed under the Solderpad Hardware
7
   License, Version 0.51 (the "License"); you may not use this file except
8
   in compliance with the License. You may obtain a copy of the License at
9
 
10
       http://solderpad.org/licenses/SHL-0.51.
11
 
12
   Unless required by applicable law or agreed to in writing, software, hardware
13
   and materials distributed under this License is distributed on an "AS IS"
14
   BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15
   implied. See the License for the specific language governing permissions
16
   and limitations under the License.
17
%*/
18
/*
19
   Implements the bi-directional high speed interface of default
20
   firmwares using the GPIF-II of FX3. It also includes an scheduler
21
   (required if both directions are used at the same time) and short
22
   packets (PKTEND).
23
 
24
   DMA0: FPGA --> FX3 transfers
25
   DMA1: FX3 --> FPGA transfers
26
*/
27
module ezusb_io (
28
        output ifclk,
29
        input reset,                    // asynchronous reset input
30
        output reset_out,               // synchronous reset output
31
        // pins
32
        input ifclk_in,
33
        inout [15:0] fd,
34
        output reg SLWR, SLRD,          // low active
35
        output reg SLOE, PKTEND,        // low active
36
        input EMPTY_FLAG, FULL_FLAG,    // almost full/empty due to flag latency of several clocks, low active
37
// signals for FPGA -> EZ-USB transfer
38
        input [15:0] DI,                // data written to EZ-USB
39
        input DI_valid,                 // 1 indicates data valid; DI and DI_valid must be hold if DI_ready is 0
40
        output DI_ready,                // 1 if new data are accepted
41
        input DI_enable,                // setting to 0 disables FPGA -> EZ-USB transfers
42
        input pktend_arm,               // 0->1 transition enables the manual PKTEND mechanism:
43
                                        // PKTEND is asserted as soon output becomes idle
44
                                        // recommended procedure for accurate packet transfers:
45
                                        //   * DI_valid goes low after last data of package
46
                                        //   * monitor PKTEND and hold DI_valid until PKTEND is asserted (PKTEND = 0)
47
        input [15:0] pktend_timeout,     // automatic PKTEN assertion after pktend_timeout*65536 clocks of no output data
48
                                        // setting to 0 disables this feature
49
        // signals for EZ-USB -> FPGA transfer
50
        output reg [15:0] DO,           // data read from EZ-USB
51
        output reg DO_valid,            // 1 indicated valid data
52
        input DO_ready,                 // setting to 1 enables writing new data to DO in next clock; DO and DO_valid are hold if DO_ready is 0
53
                                        // set to 0 to disable data reads 
54
        // debug output
55
        output [6:0] status
56
    );
57
 
58
 
59
    wire ifclk_inbuf, ifclk_fbin, ifclk_fbout, ifclk_out, locked;
60
 
61
    IBUFG ifclkin_buf (
62
        .I(ifclk_in),
63
        .O(ifclk_inbuf)
64
    );
65
 
66
    BUFG ifclk_fb_buf (
67
        .I(ifclk_fbout),
68
        .O(ifclk_fbin)
69
     );
70
 
71
    BUFG ifclk_out_buf (
72
        .I(ifclk_out),
73
        .O(ifclk)
74
     );
75
 
76
    MMCME2_BASE #(
77
       .BANDWIDTH("OPTIMIZED"),
78
       .CLKFBOUT_MULT_F(10.0),
79
       .CLKFBOUT_PHASE(0.0),
80
       .CLKIN1_PERIOD(0.0),
81
       .CLKOUT0_DIVIDE_F(10.0),
82
       .CLKOUT1_DIVIDE(1),
83
       .CLKOUT2_DIVIDE(1),
84
       .CLKOUT3_DIVIDE(1),
85
       .CLKOUT4_DIVIDE(1),
86
       .CLKOUT5_DIVIDE(1),
87
       .CLKOUT0_DUTY_CYCLE(0.5),
88
       .CLKOUT1_DUTY_CYCLE(0.5),
89
       .CLKOUT2_DUTY_CYCLE(0.5),
90
       .CLKOUT3_DUTY_CYCLE(0.5),
91
       .CLKOUT4_DUTY_CYCLE(0.5),
92
       .CLKOUT5_DUTY_CYCLE(0.5),
93
       .CLKOUT0_PHASE(0.0),
94
       .CLKOUT1_PHASE(0.0),
95
       .CLKOUT2_PHASE(0.0),
96
       .CLKOUT3_PHASE(0.0),
97
       .CLKOUT4_PHASE(0.0),
98
       .CLKOUT5_PHASE(0.0),
99
       .CLKOUT4_CASCADE("FALSE"),
100
       .DIVCLK_DIVIDE(1),
101
       .REF_JITTER1(0.0),
102
       .STARTUP_WAIT("FALSE")
103
    )  isclk_mmcm_inst (
104
       .CLKOUT0(ifclk_out),
105
       .CLKFBOUT(ifclk_fbout),
106
       .CLKIN1(ifclk_inbuf),
107
       .PWRDWN(1'b0),
108
       .RST(reset),
109
       .CLKFBIN(ifclk_fbin),
110
       .LOCKED(locked)
111
    );
112
 
113
    reg reset_ifclk = 1;
114
    reg if_out;
115
    reg [4:0] if_out_delay;
116
    reg [15:0] fd_buf;
117
    reg [15:0] resend_buf0, resend_buf1, resend_buf2, resend_buf3;
118
    reg [3:0] resend, resend_valid;
119
 
120
    reg SLRD_buf1, SLRD_buf2;
121
    reg pktend_auto, pktend_arm_buf, pktend_arm_prev;
122
    reg [31:0] pktend_cnt;
123
    reg [15:0] DO_buf1, DO_buf2, DO_buf3;
124
    reg DO_buf1_valid, DO_buf2_valid, DO_buf3_valid;
125
 
126
    wire SLRD_next, SLWR_next;
127
 
128
    // FPGA <-> EZ-USB signals
129
    assign fd = if_out ? fd_buf : {16{1'bz}};
130
 
131
    assign status = { if_out, !SLRD, !SLWR, DI_valid, DO_ready, !EMPTY_FLAG, !FULL_FLAG };
132
 
133
    assign reset_out = reset || reset_ifclk;
134
 
135
    assign DI_ready = !reset_ifclk && FULL_FLAG && if_out && !resend[0];
136
    assign SLWR_next = reset_ifclk || !FULL_FLAG || !if_out || !(resend[0] || DI_valid);
137
 
138
    assign SLRD_next = reset_ifclk || !EMPTY_FLAG || if_out || !DO_ready || DO_buf1_valid;
139
 
140
    always @ (posedge ifclk)
141
    begin
142
        reset_ifclk <= reset || !locked;
143
 
144
        SLRD <= SLRD_next;
145
        SLRD_buf1 <= SLRD;
146
        SLRD_buf2 <= SLRD_buf1;
147
 
148
        SLWR <= SLWR_next;
149
 
150
        SLOE <= reset_ifclk || if_out;
151
 
152
        // FPGA --> EZ-USB
153
        if ( reset_ifclk )
154
        begin
155
            resend <= 4'd0;
156
            resend_valid <= 4'd0;
157
        end else if ( if_out )
158
        begin
159
            if ( FULL_FLAG )
160
            begin
161
                fd_buf <= resend[0] ? resend_buf0 : DI;
162
                resend_buf0 <= resend_buf1;
163
                resend_buf1 <= resend_buf2;
164
                resend_buf2 <= resend_buf3;
165
                resend_buf3 <= DI;
166
                resend_valid <= { !resend[0] && DI_valid, resend_valid[3:1] };
167
                resend <= { 1'b0, resend[3:1] };
168
            end else
169
            begin
170
                resend <= resend_valid;         // FLAGS are received three clocks after data.
171
            end
172
        end
173
 
174
        // EZ-USB -> FPGA
175
        // SLRD -> DATA,FLAG latency is two clocks
176
        // DATA - FLAG latency is 0
177
        // if DO_ready goes low two data word have to be buffered
178
        if ( reset_ifclk )
179
        begin
180
            DO_buf1_valid = 1'b0;
181
            DO_buf2_valid = 1'b0;
182
            DO_buf3_valid = 1'b0;
183
        end else if ( EMPTY_FLAG && !SLRD_buf2 )        // EZ-USB -> FPGA: valid data
184
        begin
185
            if ( DO_ready && !DO_buf1_valid )
186
            begin
187
                DO <= fd;
188
            end else
189
            begin                                       // buffers data if DO_ready has been deasserted
190
                DO_buf1 <= fd;
191
                DO_buf2 <= DO_buf1;
192
                DO_buf3 <= DO_buf2;
193
                DO_buf1_valid <= 1'b1;
194
                DO_buf2_valid <= DO_buf1_valid;
195
                DO_buf3_valid <= DO_buf2_valid;
196
            end
197
            if ( DO_ready ) DO_valid = !DO_buf1_valid;
198
        end else if ( DO_ready )
199
        begin
200
            if ( DO_buf3_valid )                        // writes buffered data
201
            begin
202
                DO <= DO_buf3;
203
                DO_buf3_valid <= 1'b0;
204
            end else if ( DO_buf2_valid )               // writes buffered data
205
            begin
206
                DO <= DO_buf2;
207
                DO_buf2_valid <= 1'b0;
208
            end else if ( DO_buf1_valid )               // writes buffered data
209
            begin
210
                DO <= DO_buf1;
211
                DO_buf1_valid <= 1'b0;
212
            end
213
            DO_valid <= DO_buf1_valid;
214
        end
215
 
216
        // select direction
217
        if ( reset_ifclk )
218
        begin
219
            if_out_delay = 5'd0;
220
            if_out <= DI_enable;        // direction of EZ-USB interface: 1 means FPGA --> EZ_USB
221
        end else if ( SLWR && SLRD && SLWR_next && SLRD_next )
222
        begin
223
            if_out_delay <= { 1'b1, if_out_delay[4:1] };
224
            if ( if_out_delay[0] ) if_out <= DI_enable && (!DO_ready || !EMPTY_FLAG || DO_buf1_valid);
225
        end else
226
        begin
227
            if_out_delay = 5'd0;
228
        end
229
 
230
        // PKTEND processing
231
        pktend_arm_prev <= pktend_arm;
232
        if ( reset_ifclk || !SLWR || DI_valid || resend!=4'd0 || !FULL_FLAG )
233
        begin
234
            // auto mode is always enabled if data appears. It may send ZLP's.
235
            pktend_auto <= (!reset_ifclk) && (pktend_auto || !SLWR);
236
            pktend_cnt <= 32'd0;
237
            PKTEND <= 1'b1;
238
            pktend_arm_buf <= (!reset_ifclk) && ( pktend_arm_buf || ( pktend_arm && !pktend_arm_prev ) );
239
        // PKTEND must not be asserted unless a buffer is available (FULL=1)
240
        // assertion of PKTEND should also work during reading (SLRD=0), but this has not been tested
241
        end else if ( /*SLRD && SLRD_next &&*/ FULL_FLAG && ( pktend_arm_buf || ( pktend_auto && (pktend_timeout != 16'd0) && (pktend_timeout == pktend_cnt[31:16]) ) ) )
242
        begin
243
            PKTEND <= 1'b0;
244
            pktend_auto <= 1'b0;
245
            pktend_arm_buf <= 1'b0;
246
        end else
247
        begin
248
            PKTEND <= 1'b1;
249
            pktend_cnt <= pktend_cnt + 32'd1;
250
            pktend_arm_buf <= pktend_arm_buf || ( pktend_arm && !pktend_arm_prev );
251
        end
252
    end
253
 
254
endmodule
255
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.