-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathusb_ep_banked.v
166 lines (146 loc) · 4.03 KB
/
usb_ep_banked.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
module usb_ep_banked(
input clk,
input direction_in,
input setup,
input success,
input[6:0] cnt,
output reg toggle,
output bank_usb,
output reg[1:0] handshake,
output bank_in,
output bank_out,
output in_data_valid,
input ctrl_dir_in,
output reg[15:0] ctrl_rd_data,
input[15:0] ctrl_wr_data,
input[1:0] ctrl_wr_en
);
localparam
hs_ack = 2'b00,
hs_none = 2'b01,
hs_nak = 2'b10,
hs_stall = 2'b11;
reg ep_setup;
reg ep_out_full;
reg ep_out_empty;
reg ep_in_empty;
reg ep_out_stall;
reg ep_in_stall;
reg ep_out_toggle;
reg ep_in_toggle;
reg ep_in_bank;
reg[6:0] ep_in_cnt_0;
reg[6:0] ep_in_cnt_1;
reg[6:0] ep_out_cnt;
assign in_data_valid = (cnt != (ep_in_toggle? ep_in_cnt_1: ep_in_cnt_0));
assign bank_usb = direction_in? ep_in_toggle: 1'b0;
assign bank_in = ep_in_bank;
assign bank_out = 1'b0;
always @(*) begin
if (!direction_in && setup)
toggle = 1'b0;
else if (ep_setup)
toggle = 1'b1;
else if (direction_in)
toggle = ep_in_toggle;
else
toggle = ep_out_toggle;
end
always @(*) begin
if (direction_in) begin
if (!ep_in_stall && !ep_setup && !ep_in_empty) begin
handshake = hs_ack;
end else if (!ep_setup && ep_in_stall) begin
handshake = hs_stall;
end else begin
handshake = hs_nak;
end
end else begin
if (setup || (!ep_out_stall && !ep_setup && ep_out_full)) begin
handshake = hs_ack;
end else if (!ep_setup && ep_out_stall) begin
handshake = hs_stall;
end else begin
handshake = hs_nak;
end
end
end
always @(*) begin
if (ctrl_dir_in) begin
ctrl_rd_data[15:8] = ep_in_bank? ep_in_cnt_1: ep_in_cnt_0;
ctrl_rd_data[7:0] = { ep_in_bank, ep_in_toggle, ep_in_stall, 1'b0, ep_in_empty, !ep_in_empty && ep_in_toggle == ep_in_bank };
end else begin
ctrl_rd_data[15:8] = ep_out_cnt;
ctrl_rd_data[7:0] = { ep_out_toggle, ep_out_stall, ep_setup, ep_out_empty, ep_out_full };
end
end
wire flush = ctrl_wr_data[5] || ctrl_wr_data[4] || ctrl_wr_data[3];
always @(posedge clk) begin
if (success) begin
if (direction_in) begin
if (ep_in_toggle != ep_in_bank)
ep_in_empty <= 1'b1;
ep_in_toggle = !ep_in_toggle;
end else begin
if (setup)
ep_setup <= 1'b1;
ep_out_toggle = !ep_out_toggle;
ep_out_empty <= 1'b0;
ep_out_cnt <= cnt;
end
end
if (ctrl_wr_en[1] && ctrl_dir_in) begin
if (ep_in_bank)
ep_in_cnt_1 <= ctrl_wr_data[14:8];
else
ep_in_cnt_0 <= ctrl_wr_data[14:8];
end
if (ctrl_wr_en[0] && ctrl_dir_in) begin
if (ctrl_wr_data[5]) begin
ep_in_toggle = 1'b0;
ep_in_stall <= 1'b0;
ep_in_bank <= 1'b0;
end
if (ctrl_wr_data[4]) begin
ep_in_toggle = 1'b1;
ep_in_stall <= 1'b0;
ep_in_bank <= 1'b1;
end
if (ctrl_wr_data[3]) begin
ep_in_stall <= 1'b1;
ep_in_bank <= ep_in_toggle;
end
if (flush) begin
ep_in_empty <= 1'b1;
end
if (ctrl_wr_data[0]) begin
ep_in_empty <= 1'b0;
ep_in_bank <= !ep_in_bank;
end
end
if (ctrl_wr_en[0] && !ctrl_dir_in) begin
if (ctrl_wr_data[5]) begin
ep_out_toggle = 1'b0;
ep_out_stall <= 1'b0;
end
if (ctrl_wr_data[4]) begin
ep_out_toggle = 1'b1;
ep_out_stall <= 1'b0;
end
if (ctrl_wr_data[3])
ep_out_stall <= 1'b1;
if (flush) begin
ep_out_full <= 1'b0;
ep_out_empty <= 1'b1;
end
if (ctrl_wr_data[2])
ep_setup <= 1'b0;
if (ctrl_wr_data[1]) begin
ep_out_empty <= 1'b1;
ep_out_full <= 1'b0;
end
if (ctrl_wr_data[0])
ep_out_full <= 1'b1;
end
end
endmodule