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-fx2/] [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 EZ-USB Slave FIFO interface for both
20
   directions. It also includes an scheduler (required if both
21
   directions are used at the same time) and short packets (PKTEND).
22
*/
23
module ezusb_io #(
24
        parameter OUTEP = 2,            // EP for FPGA -> EZ-USB transfers
25
        parameter INEP = 6,             // EP for EZ-USB -> FPGA transfers 
26
        parameter TARGET = ""           // Target FPGA: "A7": Artix 7, "" all others
27
    ) (
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, PKTEND,
35
        output SLRD, SLOE,
36
        output [1:0] FIFOADDR,
37
        input EMPTY_FLAG, FULL_FLAG,
38
        // signals for FPGA -> EZ-USB transfer
39
        input [15:0] DI,                // data written to EZ-USB
40
        input DI_valid,                 // 1 indicates data valid; DI and DI_valid must be hold if DI_ready is 0
41
        output DI_ready,                // 1 if new data are accepted
42
        input DI_enable,                // setting to 0 disables FPGA -> EZ-USB transfers
43
        input pktend_arm,               // 0->1 transition enables the manual PKTEND mechanism:
44
                                        // PKTEND is asserted as soon output becomes idle
45
                                        // recommended procedure for accurate packet transfers:
46
                                        //   * DI_valid goes low after last data of package
47
                                        //   * monitor PKTEND and hold DI_valid until PKTEND is asserted (PKTEND = 0)
48
        input [15:0] pktend_timeout,    // automatic PKTEN assertion after pktend_timeout*65536 clocks of no output data
49
                                        // setting to 0 disables this feature
50
        // signals for EZ-USB -> FPGA transfer
51
        output reg [15:0] DO,           // data read from EZ-USB
52
        output reg DO_valid,            // 1 indicated valid data
53
        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
54
                                        // set to 0 to disable data reads 
55
        // debug output
56
        output [3:0] status
57
    );
58
 
59
 
60
    wire locked;
61
 
62
    generate
63
        if ( TARGET == "A7") begin: gen_artix7_clocks
64
 
65
            wire ifclk_inbuf, ifclk_fbin, ifclk_fbout, ifclk_out;
66
 
67
            IBUFG ifclkin_buf (
68
                .I(ifclk_in),
69
                .O(ifclk_inbuf)
70
            );
71
 
72
            BUFG ifclk_fb_buf (
73
                .I(ifclk_fbout),
74
                .O(ifclk_fbin)
75
            );
76
 
77
            BUFG ifclk_out_buf (
78
                .I(ifclk_out),
79
                .O(ifclk)
80
            );
81
 
82
            MMCME2_BASE #(
83
                .BANDWIDTH("OPTIMIZED"),
84
                .CLKFBOUT_MULT_F(20.0),
85
                .CLKFBOUT_PHASE(0.0),
86
                .CLKIN1_PERIOD(0.0),
87
                .CLKOUT0_DIVIDE_F(20.0),
88
                .CLKOUT1_DIVIDE(1),
89
                .CLKOUT2_DIVIDE(1),
90
                .CLKOUT3_DIVIDE(1),
91
                .CLKOUT4_DIVIDE(1),
92
                .CLKOUT5_DIVIDE(1),
93
                .CLKOUT0_DUTY_CYCLE(0.5),
94
                .CLKOUT1_DUTY_CYCLE(0.5),
95
                .CLKOUT2_DUTY_CYCLE(0.5),
96
                .CLKOUT3_DUTY_CYCLE(0.5),
97
                .CLKOUT4_DUTY_CYCLE(0.5),
98
                .CLKOUT5_DUTY_CYCLE(0.5),
99
                .CLKOUT0_PHASE(0.0),
100
                .CLKOUT1_PHASE(0.0),
101
                .CLKOUT2_PHASE(0.0),
102
                .CLKOUT3_PHASE(0.0),
103
                .CLKOUT4_PHASE(0.0),
104
                .CLKOUT5_PHASE(0.0),
105
                .CLKOUT4_CASCADE("FALSE"),
106
                .DIVCLK_DIVIDE(1),
107
                .REF_JITTER1(0.0),
108
                .STARTUP_WAIT("FALSE")
109
            )  ifclk_mmcm_inst (
110
                .CLKOUT0(ifclk_out),
111
                .CLKFBOUT(ifclk_fbout),
112
                .CLKIN1(ifclk_inbuf),
113
                .PWRDWN(1'b0),
114
                .RST(reset),
115
                .CLKFBIN(ifclk_fbin),
116
                .LOCKED(locked)
117
            );
118
 
119
        end else begin: gen_other_clocks
120
 
121
            IBUFG ifclkin_buf (
122
                .I(ifclk_in),
123
                .O(ifclk)
124
            );
125
 
126
            assign locked = 1'b1;
127
 
128
        end
129
    endgenerate
130
 
131
    reg reset_ifclk = 1;
132
    reg if_out, if_in;
133
    reg [4:0] if_out_buf;
134
    reg [15:0] fd_buf;
135
    reg resend;
136
    reg SLRD_buf;
137
    reg pktend_auto, pktend_arm_buf, pktend_arm_prev;
138
    reg [31:0] pktend_cnt;
139
 
140
    // FPGA <-> EZ-USB signals
141
    assign SLOE = if_out;
142
//    assign FIFOADDR[0] = 1'b0;
143
//    assign FIFOADDR[1] = !if_out;
144
    assign FIFOADDR = ( if_out ? (OUTEP/2-1) : (INEP/2-1) ) & 2'b11;
145
    assign fd = if_out ? fd_buf : {16{1'bz}};
146
    assign SLRD = SLRD_buf || !DO_ready;
147
 
148
    assign status = { !SLRD_buf, !SLWR, resend, if_out };
149
 
150
    assign DI_ready = !reset_ifclk && FULL_FLAG && if_out & if_out_buf[4] && !resend;
151
    assign reset_out = reset || reset_ifclk;
152
 
153
    always @ (posedge ifclk)
154
    begin
155
        reset_ifclk <= reset || !locked;
156
        // FPGA -> EZ-USB
157
        if ( reset_ifclk )
158
        begin
159
            SLWR <= 1'b1;
160
            if_out <= DI_enable;  // direction of EZ-USB interface: 1 means FPGA -> EZ_USB 
161
            resend <= 1'b0;
162
            SLRD_buf <= 1'b1;
163
        end else if ( FULL_FLAG && if_out && if_out_buf[4] && ( resend || DI_valid) )   // FPGA -> EZ-USB
164
        begin
165
            SLWR <= 1'b0;
166
            SLRD_buf <= 1'b1;
167
            resend <= 1'b0;
168
            if ( !resend ) fd_buf <= DI;
169
        end else if ( EMPTY_FLAG && !if_out && !if_out_buf[4] && DO_ready )             // EZ-USB -> FPGA
170
        begin
171
            SLWR <= 1'b1;
172
            DO <= fd;
173
            SLRD_buf <= 1'b0;
174
        end else if (if_out == if_out_buf[4])
175
        begin
176
            if ( !SLWR && !FULL_FLAG ) resend <= 1'b1;  // FLAGS are received two clocks after data. If FULL_FLAG was asserted last data was ignored and has to be re-sent.
177
            SLRD_buf <= 1'b1;
178
            SLWR <= 1'b1;
179
            if_out <= DI_enable && (!DO_ready || !EMPTY_FLAG);
180
        end
181
        if_out_buf <= reset_ifclk ? {5{!DI_enable}} : { if_out_buf[3:0], if_out };
182
        if ( DO_ready ) DO_valid <= !if_out && !if_out_buf[4] && EMPTY_FLAG && !SLRD_buf;  // assertion of SLRD_buf takes two clocks to take effect
183
 
184
        // PKTEND processing
185
        pktend_arm_prev <= pktend_arm;
186
        if ( reset_ifclk || !SLWR || resend || DI_valid || !FULL_FLAG )
187
        begin
188
            // auto mode is always enabled if data appears. It may send ZLP's.
189
            pktend_auto <= !reset_ifclk && (pktend_auto || !SLWR);
190
            pktend_cnt <= 32'd0;
191
            PKTEND <= 1'b1;
192
            pktend_arm_buf <= (!reset_ifclk) && ( pktend_arm_buf || ( pktend_arm && !pktend_arm_prev ) );
193
        // PKTEND must not be asserted unless a buffer is available (FULL=1)
194
        end else if ( if_out && if_out_buf[4] && ( pktend_arm_buf || ( pktend_auto && (pktend_timeout != 16'd0) && (pktend_timeout <= pktend_cnt[31:16]) ) ) )
195
        begin
196
            PKTEND <= 1'b0;
197
            pktend_auto <= 1'b0;
198
            pktend_arm_buf <= 1'b0;
199
        end else
200
        begin
201
            PKTEND <= 1'b1;
202
            pktend_cnt <= pktend_cnt + 32'd1;
203
            pktend_arm_buf <= pktend_arm_buf || ( pktend_arm && !pktend_arm_prev );
204
        end
205
    end
206
 
207
endmodule
208
 

powered by: WebSVN 2.1.0

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