-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathusb_ep.v
152 lines (132 loc) · 3.51 KB
/
usb_ep.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
module usb_ep(
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_full;
reg ep_out_stall;
reg ep_in_stall;
reg ep_out_toggle;
reg ep_in_toggle;
reg[6:0] ep_in_cnt;
reg[6:0] ep_out_cnt;
assign in_data_valid = (cnt != ep_in_cnt);
assign bank_usb = 1'b0;
assign bank_in = 1'b0;
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_full) 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_cnt;
ctrl_rd_data[7:0] = { ep_in_toggle, ep_in_stall, 1'b0, !ep_in_full, ep_in_full };
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
ep_in_full <= 1'b0;
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_full <= 1'b0;
ep_out_cnt <= cnt;
end
end
if (ctrl_wr_en[1] && ctrl_dir_in) begin
ep_in_cnt <= 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;
end
if (ctrl_wr_data[4]) begin
ep_in_toggle <= 1'b1;
ep_in_stall <= 1'b0;
end
if (ctrl_wr_data[3])
ep_in_stall <= 1'b1;
if (flush)
ep_in_full <= 1'b0;
if (ctrl_wr_data[0])
ep_in_full <= 1'b1;
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])
ep_out_empty <= 1'b1;
if (ctrl_wr_data[0])
ep_out_full <= 1'b1;
end
end
endmodule