📄 udevctl.v
字号:
sendnak <= 1'b0;
if (usbreset)
sendack <= 1'b0;
else if (nextctlst == CTLSENDACK)
sendack <= 1'b1;
else if (acksent)
sendack <= 1'b0;
if (usbreset)
senddata <= 1'b0;
else if (nextctlst == CTLSENDDATA)
senddata <= 1'b1;
else if (datasent)
senddata <= 1'b0;
if (usbreset)
begin
firstbytevalid <= 1'b0;
secondbytevalid <= 1'b0;
end
else if (grabdata)
//else if (grabdata || grabsetup) //JAKE
begin
firstbytevalid <= 1'b1;
secondbytevalid <= firstbytevalid;
end
else if (rcvpacketok || rcvpacketnotok) // at end of packet, get rid of both
begin
firstbytevalid <= 1'b0;
secondbytevalid <= 1'b0;
end
if (grabdata)
// if (grabdata ||grabsetup) //JAKE
begin
firstbyte <= rcvdatabyte;
secondbyte <= firstbyte;
end
if (rcvendpointvalid) currentendp <= rcvendpoint;
if (rcvaddressvalid) currentaddr <= rcvaddress;
end
// state machine for doing the device control
//STATE MACHINE
always @(posedge usbclock)
begin
if (usbreset)
ctlst <= CTLIDLE;
else
ctlst <= nextctlst;
end
always @(ctlst or usbreset or rcvsetup or rcvdata or rcvdatain or rcvdataout or rcvack or
rcvendpointvalid or rcvaddressvalid or rcvaddress or rcvendpoint or
rcvpacketok or rcvpacketnotok or naksent or isoendpoint or xmitlastbyte or
acksent or addressmatch or stallsent or endpointzerotogglebit or endpoint0active or
endpointrdready or endpointwrready or endpointrdstall or endpointwrstall or
endpointouttogglebits or currentendp or setupcycle or rcvdatatogglebit or
turnaround or endpointrdmatch or endpointwrmatch or setupdirection or grabdata or
sendzerolengthpkt)
begin
if (usbreset)
nextctlst = CTLIDLE;
else
case (ctlst) // synopsys parallel_case full_case
CTLIDLE:
begin
case (1'b1) // synopsys parallel_case full_case
rcvsetup:
nextctlst = CTLSETUP;
rcvdata: // wasn't for us as identified during out packet
nextctlst = CTLIDLE;
rcvdatain:
nextctlst = CTLDIN;
rcvdataout:
nextctlst = CTLDOUT;
rcvack: // isn't for us since we didn't just send data
nextctlst = CTLIDLE;
default:
nextctlst = CTLIDLE;
endcase
end
CTLSETUP:
begin
if (rcvpacketnotok)
nextctlst = CTLIDLE;
else if (rcvpacketok && addressmatch && endpoint0active) // packet is ok and matches us
nextctlst = CTLWAIT4SETUP;
else if (rcvpacketok)
nextctlst = CTLIDLE;
else
nextctlst = CTLSETUP;
end
CTLDIN:
begin
if (rcvpacketnotok)
nextctlst = CTLIDLE;
// rcvpacketok means crc5 was good
// first condition is the null data on a control data in
else if (rcvpacketok && addressmatch && endpoint0active && setupcycle && (setupdirection == HOSTTODEV))
nextctlst = CTLSENDDATA; // packet is ok and matches us
else if (rcvpacketok && addressmatch && endpointrdmatch && endpointrdready && ~endpointrdstall)
nextctlst = CTLSENDDATA; // packet is ok and matches us
else if (rcvpacketok && addressmatch && endpointrdmatch && endpointrdstall && ~isoendpoint)
nextctlst = CTLSENDSTALL; // endpoint is stalled
else if (rcvpacketok && addressmatch && endpointrdmatch && ~endpointrdready && ~isoendpoint)
nextctlst = CTLSENDNAK; // endpoint isn't ready, not stalled
else if (rcvpacketok) // not for us
nextctlst = CTLIDLE;
else
nextctlst = CTLDIN;
end
CTLDOUT:
begin
if (rcvpacketnotok)
nextctlst = CTLIDLE;
else if (rcvpacketok && addressmatch && endpointwrmatch) // packet is ok and matches us
nextctlst = CTLWAIT4DATA;
else if (rcvpacketok) // either bad or not us
nextctlst = CTLIDLE;
else
nextctlst = CTLDOUT;
end
CTLWAIT4SETUP: // here during the intial setup token of a setup cycle
// waiting for the data0 host transmit of the setup request packet
begin
if (rcvdata)
nextctlst = CTLGRABSETUP;
else if (rcvpacketnotok || rcvpacketok || turnaround) // some other packet came ?!?
nextctlst = CTLIDLE; // or nothing coming? - give up and go to idle
else
nextctlst = CTLWAIT4SETUP;
end
CTLWAIT4DATA: // once here, we know the address and endpoint match, just check endpoint is ok
begin
// first condition is the null data on a control data in
if (rcvdata && sendzerolengthpkt && endpoint0active && (setupdirection == DEVTOHOST) && (endpointzerotogglebit == rcvdatatogglebit)) // null data, send ack
nextctlst = CTLSENDACK;
else if (rcvdata && ~isoendpoint && (~endpointwrready || endpointwrstall)) // not ready or stalled
nextctlst = CTLIGNOREDATA;
else if (rcvdata)
begin
// don't check toggle bit if iso endpoint
if (((endpointouttogglebits[currentendp] == rcvdatatogglebit) && ~endpoint0active) ||
((endpointzerotogglebit == rcvdatatogglebit) && endpoint0active) ||
isoendpoint)
nextctlst = CTLGRABDATA;
else // toggle mismatch, must have seen this data already
// we can go straight to sendack, since we want to send
// ack no matter what and the xmit will wait for incoming
// data to complete first
nextctlst = CTLSENDACK;
end //if (rcvdata)
else if (rcvpacketnotok || rcvpacketok || turnaround) // some other packet came ?!?
nextctlst = CTLIDLE; // or nothing coming? - give up and go to idle
else
nextctlst = CTLWAIT4DATA;
end
CTLIGNOREDATA: // got here because we are stalled or not ready, but must check for good packet
// before sending NAK or STALL
if (rcvpacketnotok)
nextctlst = CTLIDLE;
else if (rcvpacketok && endpointwrstall) // endpoint is stalled
nextctlst = CTLSENDSTALL;
else if (rcvpacketok) // don't recheck ready here,
nextctlst = CTLSENDNAK; // if we got here, we missed data already
else
nextctlst = CTLIGNOREDATA;
CTLGRABDATA:
begin
if (rcvpacketnotok || (rcvpacketok && isoendpoint)) // no acks for iso endpoints
nextctlst = CTLIDLE;
else if (rcvpacketok)
nextctlst = CTLSENDACK;
else if (~endpointwrready && ~isoendpoint && grabdata)// overflowed! (iso's can't overflow)
nextctlst = CTLOVERFLOW;
else
nextctlst = CTLGRABDATA;
end
CTLGRABSETUP:
begin
if (rcvpacketnotok)
nextctlst = CTLIDLE;
else if (rcvpacketok)
nextctlst = CTLSENDACK;
else
nextctlst = CTLGRABSETUP;
end
CTLOVERFLOW:
begin
if (rcvpacketnotok)
nextctlst = CTLIDLE;
else if (rcvpacketok)
nextctlst = CTLSENDNAK;
else
nextctlst = CTLOVERFLOW;
end
CTLSENDDATA:
begin
if (xmitlastbyte && ~isoendpoint) // no acks for isochronous endpoints
nextctlst = CTLWAIT4ACK;
else if (xmitlastbyte)
nextctlst = CTLIDLE;
else
nextctlst = CTLSENDDATA;
end
CTLWAIT4ACK:
begin
// TEMP - this might technically be incorrect, I should wait for packetok, in case of badpidbar
if (rcvack)
nextctlst = CTLIDLE;
else if (rcvpacketnotok || rcvpacketok || turnaround) // some other packet came ?!?
nextctlst = CTLIDLE; // or nothing coming? - give up and go to idle
else
nextctlst = CTLWAIT4ACK;
end
CTLSENDACK:
begin
if (acksent)
nextctlst = CTLIDLE;
else
nextctlst = CTLSENDACK;
end
CTLSENDNAK:
begin
if (naksent)
nextctlst = CTLIDLE;
else if (rcvpacketnotok || rcvpacketok) // some other packet came ?!?
nextctlst = CTLIDLE; // give up and go to idle
else
nextctlst = CTLSENDNAK;
end
CTLSENDSTALL:
begin
if (stallsent)
nextctlst = CTLIDLE;
else if (rcvpacketnotok || rcvpacketok) // some other packet came ?!?
nextctlst = CTLIDLE; // give up and go to idle
else
nextctlst = CTLSENDSTALL;
end
endcase
end
// for waves
// setup direction is high for Device -> Host,
wire [63:0] setupreqpkt = {setuplength, // bytes 7 and 6
setupwindex[15:0], // bytes 5 and 4
setupvalue1, // byte 3 wValueH on get descriptor - type dev,cfg, or string
setupvalue0, // byte 2 wValueL - address on setaddress
setuprequest, // byte 1 request field
setupdirection,setuptype,3'b000,setuprecipient}; // byte lane 0
always @(setupreqpkt or setupbyteaddr)
begin
case (setupbyteaddr) // synopsys parallel_case full_case
3'h0: setupdata = setupreqpkt[7:0];
3'h1: setupdata = setupreqpkt[15:8];
3'h2: setupdata = setupreqpkt[23:16];
3'h3: setupdata = setupreqpkt[31:24];
3'h4: setupdata = setupreqpkt[39:32];
3'h5: setupdata = setupreqpkt[47:40];
3'h6: setupdata = setupreqpkt[55:48];
3'h7: setupdata = setupreqpkt[63:56];
endcase
end
// make the ascii version of the ctl state
// synopsys translate_off
reg [8*11:1] ctlstate;
always @(ctlst)
case (ctlst)
CTLIDLE : ctlstate = "CTLIDLE";
CTLSETUP : ctlstate = "CTLSETUP";
CTLDIN : ctlstate = "CTLDIN";
CTLDOUT : ctlstate = "CTLDOUT";
CTLWAIT4SETUP : ctlstate = "CTLWAIT4SETUP";
CTLWAIT4DATA : ctlstate = "CTLWAIT4DATA";
CTLIGNOREDATA : ctlstate = "CTLIGNOREDATA";
CTLOVERFLOW : ctlstate = "CTLOVERFLOW";
CTLWAIT4ACK : ctlstate = "CTLWAIT4ACK";
CTLGRABDATA : ctlstate = "CTLGRABDATA";
CTLSENDDATA : ctlstate = "CTLSENDDATA";
CTLSENDACK : ctlstate = "CTLSENDACK";
CTLSENDNAK : ctlstate = "CTLSENDNAK";
CTLSENDSTALL : ctlstate = "CTLSENDSTALL";
CTLGRABSETUP : ctlstate = "CTLGRABSETUP";
default: ctlstate = "ILLEGAL STATE";
endcase
// synopsys translate_on
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -