-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathusbfs_packet_rx.v
148 lines (126 loc) · 4.75 KB
/
usbfs_packet_rx.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
//--------------------------------------------------------------------------------------------------------
// Module : usbfs_packet_rx
// Type : synthesizable, IP's sub module
// Standard: Verilog 2001 (IEEE1364-2001)
// Function: USB Full Speed (12Mbps) device packet receiver and parser
// extract PID, ADDR, and data bytes from RX packet, check and report CRC5 and CRC16 status
//--------------------------------------------------------------------------------------------------------
module usbfs_packet_rx (
input wire rstn,
input wire clk,
// RX bit-level signals
input wire rx_sta,
input wire rx_ena,
input wire rx_bit,
input wire rx_fin,
// RX packet-level signals
output reg [ 3:0] rp_pid,
output reg [10:0] rp_addr,
output reg rp_byte_en,
output reg [ 7:0] rp_byte,
output reg rp_fin,
output reg rp_okay
);
initial rp_pid = 4'h0;
initial rp_addr = 11'h0;
initial rp_byte_en = 1'b0;
initial rp_byte = 8'h0;
initial rp_fin = 1'b0;
initial rp_okay = 1'b0;
function [4:0] CRC5;
input [4:0] crc;
input inbit;
reg xorbit;
begin
xorbit = crc[4] ^ inbit;
CRC5 = {crc[3:0],1'b0} ^ {2'b0,xorbit,1'b0,xorbit};
end
endfunction
function [15:0] CRC16;
input [15:0] crc;
input inbit;
reg xorbit;
begin
xorbit = crc[15] ^ inbit;
CRC16 = {crc[14:0],1'b0} ^ {xorbit,12'b0,xorbit,1'b0,xorbit};
end
endfunction
reg rx_valid = 1'b0;
reg [ 1:0] rx_bytecnt = 2'b0;
reg [ 4:0] rx_bcnt = 5'h0;
reg [ 2:0] rx_cnt = 3'h0;
reg [23:0] rx_shift = 24'h0;
reg [ 4:0] rx_crc5 = 5'h1F;
reg [15:0] rx_crc16 = 16'hFFFF;
wire[23:0] rx_shift_next = {rx_bit, rx_shift[23:1]};
always @ (posedge clk or negedge rstn)
if (~rstn) begin
rp_pid <= 4'h0;
rp_addr <= 11'h0;
rp_byte_en <= 1'b0;
rp_byte <= 8'h0;
rx_valid <= 1'b0;
rx_bytecnt <= 2'b0;
rx_bcnt <= 5'h0;
rx_cnt <= 3'h0;
rx_shift <= 24'h0;
rx_crc5 <= 5'h1F;
rx_crc16 <= 16'hFFFF;
end else begin
rp_byte_en <= 1'b0;
if (rx_sta) begin
rp_pid <= 4'h0;
rx_valid <= 1'b0;
rx_bytecnt <= 2'b0;
rx_bcnt <= 5'h0;
rx_cnt <= 3'h0;
rx_shift <= 24'h0;
rx_crc5 <= 5'h1F;
rx_crc16 <= 16'hFFFF;
end else if (rx_ena) begin
rx_cnt <= rx_cnt + 3'd1;
rx_shift <= rx_shift_next;
if (rx_bytecnt != 2'b0) begin
if (rx_bcnt >= 5'd5)
rx_crc5 <= CRC5(rx_crc5, rx_shift_next[18]);
if (rx_bcnt >= 5'd16)
rx_crc16 <= CRC16(rx_crc16, rx_shift_next[7]);
if (rx_bcnt != 5'd31)
rx_bcnt <= rx_bcnt + 5'd1;
end
if (rx_cnt == 3'd7) begin
if (rx_bytecnt == 2'd0) begin
if ( & (rx_shift_next[23:20] ^ rx_shift_next[19:16]) ) begin // PID valid
rx_valid <= 1'b1;
rp_pid <= rx_shift_next[19:16];
end
end
if (rx_bytecnt == 2'd2 && rx_valid && rp_pid[1:0] == 2'b01)
rp_addr <= rx_shift_next[18:8];
if (rx_bytecnt == 2'd3 && rx_valid && rp_pid[1:0] == 2'b11) begin
rp_byte_en <= 1'b1;
rp_byte <= rx_shift_next[7:0];
end
if (rx_bytecnt != 2'd3)
rx_bytecnt <= rx_bytecnt + 2'd1;
end
end
end
always @ (posedge clk or negedge rstn)
if (~rstn) begin
rp_fin <= 1'b0;
rp_okay <= 1'b0;
end else begin
rp_fin <= rx_fin;
case (rp_pid[1:0])
2'b01 : // token packet //
rp_okay <= rx_valid && (~{rx_crc5[0],rx_crc5[1],rx_crc5[2],rx_crc5[3],rx_crc5[4]} == rx_shift[23:19]);
2'b10 : // handshake packet //
rp_okay <= rx_valid;
2'b11 : // data packet //
rp_okay <= rx_valid && (~{rx_crc16[0],rx_crc16[1],rx_crc16[2],rx_crc16[3],rx_crc16[4],rx_crc16[5],rx_crc16[6],rx_crc16[7],rx_crc16[8],rx_crc16[9],rx_crc16[10],rx_crc16[11],rx_crc16[12],rx_crc16[13],rx_crc16[14],rx_crc16[15]} == rx_shift[23:8]);
default: // special packet //
rp_okay <= 1'b0;
endcase
end
endmodule