📄 usiepkt.v
字号:
/******************************************
Filename: siepkt.v 1.22
******************************************/
/*
This module creates and encodes outgoing data packets.
It takes requests from the device inteface to "senddata,
sendnak, sendack, sendstall" and generates sync,
pid, data bytes, and eop. The bit serial data are sent to
the nrzo (bit stuffer and nrzi encoder) and the data bytes
come from the device interface. The packet encoder sends
an "ack" after each packet is sent (acksent, etc.).
*/
module Usiepkt
(
// inputs from bus/dpll/nrzo/crc
testmode,
testreset,
usbclock,
syncreset,
usbreset,
nextxmitdata,
oktoxmit,
xmitcrcout,
// inputs from device/function
xmitlastbyte,
xmitdatatogglebit,
xmitdatabyte,
senddata,
sendnak,
sendack,
sendstall,
// outputs to bus
xmitactive,
xmitdatabit,
xmitidle,
xmitsendse0,
xmitcrc16data,
xmitcrc16send,
xmitdatavalid,
// outputs to device/function
nextxmitbyte,
datasent,
stallsent,
acksent,
naksent
);
`include "Usiepktdef.v"
`include "Uusbdef.v"
// inputs from bus/dpll
input testmode;
input testreset;
input usbclock;
input syncreset;
input usbreset; // synopsys sync_set_reset "usbreset"
input nextxmitdata;
input oktoxmit;
input xmitcrcout;
// inputs from device/function
input xmitlastbyte;
input xmitdatatogglebit;
input [7:0] xmitdatabyte;
input senddata;
input sendnak;
input sendack;
input sendstall;
// outputs to bus
output xmitactive;
output xmitdatabit;
output xmitidle;
output xmitsendse0;
output xmitcrc16data;
output xmitcrc16send;
output xmitdatavalid;
// outputs to device/function
output nextxmitbyte;
output datasent;
output stallsent;
output acksent;
output naksent;
reg [7:0] outgoingdatabyte;
reg xmitdatabit;
reg xmitidle;
reg xmitsendse0;
reg xmitcrc16data;
reg xmitcrc16send;
reg xmitdatavalid;
reg nextxmitbyte;
reg datasent;
reg stallsent;
reg acksent;
reg naksent;
reg [3:0] bitcount;
reg resetbitcount;
reg [9:0] prevpktst, pktst, nextpktst;
reg [3:0] currentpid;
// used to register this, but don't need to
// wire thisbyteislast = xmitlastbyte;
// special aysnc flop logic for usbclockout
wire rstn;
assign rstn = (testmode)? testreset : ~syncreset;
dffr asyncflop (
.q (xmitactive),
.d (nextpktst != PKTIDLE),
.clk (usbclock),
.rstn (rstn)
);
always @(posedge usbclock)
begin
datasent <= ((pktst == PKTCRC16) && bitcount == 4'h0);
stallsent <= ((pktst == PKTSTALL) && bitcount == 4'h0);
acksent <= ((pktst == PKTACK) && bitcount == 4'h0);
naksent <= ((pktst == PKTNAK) && bitcount == 4'h0);
xmitsendse0 <= ((nextpktst == PKTEOP) && (bitcount != 4'h1));
xmitidle <= ((nextpktst == PKTIDLE) ||
((nextpktst == PKTEOP) && bitcount == 4'h1));
xmitdatavalid <= nextxmitdata; // gets qualified in crc with crc16data
if (usbreset)
xmitcrc16data <= 1'b0;
else if (nextpktst == PKTDATA)
xmitcrc16data <= 1'b1;
else
xmitcrc16data <= 1'b0;
if (usbreset)
xmitcrc16send <= 1'b0;
else if (nextpktst == PKTCRC16)
xmitcrc16send <= 1'b1;
else
xmitcrc16send <= 1'b0;
if (usbreset)
nextxmitbyte <= 1'b0;
// ask for next byte if sending data and count is 0 and count is advancing (no double pumps)
else if ((pktst == PKTDATA) && (bitcount == 4'h0) && nextxmitdata)
nextxmitbyte <= 1'b1;
else
nextxmitbyte <= 1'b0;
if (resetbitcount)
bitcount <= 1'b0;
else if (nextxmitdata)
bitcount <= bitcount + 1'b1;
case(nextpktst) // synopsys full_case parallel_case
PKTDPID : currentpid <= (xmitdatatogglebit) ? PIDDATA1 : PIDDATA0;
PKTACK : currentpid <= PIDACK;
PKTSTALL : currentpid <= PIDSTALL;
PKTNAK : currentpid <= PIDNAK;
// default : currentpid <= currentpid;
endcase
if (nextpktst == PKTDATA && bitcount == 4'h7) // works coming out of PID
outgoingdatabyte <= xmitdatabyte; // and within data!
end
// state machine for decoding data from the usb
always @(posedge usbclock)
begin
if (usbreset)
pktst <= PKTIDLE;
else
pktst <= nextpktst;
prevpktst <= pktst;
end
//synopsys sync_set_reset_local infer_sync "usbreset"
always @(pktst or usbreset or sendack or sendnak or senddata or
xmitdatatogglebit or bitcount or
oktoxmit or xmitlastbyte or
outgoingdatabyte or sendstall or currentpid or xmitcrcout or nextxmitdata)
begin : infer_sync
if (usbreset)
begin
nextpktst = PKTIDLE;
resetbitcount = 1'b1;
xmitdatabit = 1'b1;
end
else
case (pktst) // synopsys parallel_case full_case
PKTIDLE:
begin
xmitdatabit = 1'b1;
resetbitcount = 1'b1;
if ((sendack || sendnak || sendstall || senddata) && oktoxmit) // need to do something!
begin
nextpktst = PKTSYNC;
end
else
begin
nextpktst = PKTIDLE;
end
end
PKTSYNC:
begin
if (bitcount != 4'h7)
begin
resetbitcount = 1'b0;
xmitdatabit = 1'b0;
nextpktst = PKTSYNC;
end
else if (sendstall) // last bit of sync, prioritize for which packet to send
begin
resetbitcount = 1'b1;
xmitdatabit = 1'b1;
nextpktst = PKTSTALL;
end
else if (sendnak) // last bit of sync, prioritize for which packet to send
begin
resetbitcount = 1'b1;
xmitdatabit = 1'b1;
nextpktst = PKTNAK;
end
else if (sendack) // last bit of sync, prioritize for which packet to send
begin
resetbitcount = 1'b1;
xmitdatabit = 1'b1;
nextpktst = PKTACK;
end
else
begin
resetbitcount = 1'b1;
xmitdatabit = 1'b1;
nextpktst = PKTDPID;
end
end
PKTDPID:
begin
if (bitcount[2] == 1'b0) // less than 4
xmitdatabit = currentpid[bitcount[1:0]];
else
xmitdatabit = ~currentpid[bitcount[1:0]];
if ((bitcount == 4'h7) && nextxmitdata)
begin
resetbitcount = 1'b1;
if (xmitlastbyte) // support zero length data!
nextpktst = PKTCRC16;
else
nextpktst = PKTDATA;
end
else
begin
resetbitcount = 1'b0;
nextpktst = PKTDPID;
end
end
PKTACK, PKTNAK, PKTSTALL:
begin
if (bitcount[2] == 1'b0) // less than 4
xmitdatabit = currentpid[bitcount[1:0]];
else
xmitdatabit = ~currentpid[bitcount[1:0]];
if ((bitcount == 4'h7) && nextxmitdata)
begin
resetbitcount = 1'b1;
nextpktst = PKTEOP;
end
else
begin
resetbitcount = 1'b0;
nextpktst = pktst;
end
end
PKTEOP:
begin
xmitdatabit = 1'b1; // send 1, but really will be se0
if (bitcount == 4'h2) // 2 ticks of se0, then one idle
begin
resetbitcount = 1'b1;
nextpktst = PKTIDLE;
end
else
begin
resetbitcount = 1'b0;
nextpktst = PKTEOP;
end
end
PKTDATA:
begin
xmitdatabit = outgoingdatabyte[bitcount];
if ((bitcount == 4'h7) && nextxmitdata) // last bit of byte
resetbitcount = 1'b1;
else
resetbitcount = 1'b0;
if (xmitlastbyte && (bitcount == 4'h7) && nextxmitdata) // last bit of byte
begin
nextpktst = PKTCRC16;
end
else
begin
nextpktst = PKTDATA;
end
end
PKTCRC16:
begin
xmitdatabit = xmitcrcout; // crc (combinatorial) from generator
if ((bitcount != 4'hf) || ~nextxmitdata)
begin
resetbitcount = 1'b0;
nextpktst = PKTCRC16;
end
else
begin
resetbitcount = 1'b1;
nextpktst = PKTEOP;
end
end
endcase
end
// make the ascii version of the packet state
// synopsys translate_off
reg [8*10:1] pktstate;
always @(pktst)
case (pktst)
PKTIDLE : pktstate = "PKTIDLE";
PKTSYNC : pktstate = "PKTSYNC";
PKTDPID : pktstate = "PKTDPID";
PKTDATA : pktstate = "PKTDATA";
PKTCRC16 : pktstate = "PKTCRC16";
PKTNAK : pktstate = "PKTNAK";
PKTACK : pktstate = "PKTACK";
PKTSTALL : pktstate = "PKTSTALL";
PKTERROR : pktstate = "PKTERROR";
PKTEOP : pktstate = "PKTEOP";
endcase
// synopsys translate_on
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -