📄 usiecntr.v
字号:
/******************************************
Filename: siecntr.v 1.14
******************************************/
/*
The sie counter module counts active and inactive and se0. If inactive
it first detects turnaround 17 clocks, and signals to the device that a
response, if expected, isn't coming. If it is inactive for a LONG time
it turns on suspend. If it sees se0 for MAXSE0 (33 clocks) it signals
reset
*/
module Usiecntr
(
// inputs
usbclock,
syncreset,
syncidle,
syncse0,
xmitactive,
vpin,
resumen,
testmode,
testreset,
// outputs
turnaround,
se0reset,
suspend,
oktoxmit
);
`include "Usiecntrdef.v"
input usbclock;
input syncreset; // synopsys sync_set_reset "syncreset"
input syncidle;
input syncse0;
input xmitactive;
input vpin;
input resumen;
input testmode;
input testreset;
output suspend;
output turnaround;
output se0reset;
output oktoxmit;
reg [15:0] cyclecount;
reg resetsuspend;
reg oktoxmit;
reg resetturnaround;
reg turnaround;
reg resetse0reset;
reg se0reset;
reg [2:0] cntrst, nextcntrst;
wire stayinsuspend = ((cntrst == CNTRSLEEP) && vpin && resumen);
wire rstn ;
// special aysnc flop logic for usbclockout
assign rstn = (testmode)? testreset : (~(syncreset || ~vpin || ~resumen));
dffr asyncflop (
.q (suspend),
.d (stayinsuspend),
.clk (usbclock),
.rstn (rstn) // either reset high or resumen or vpin low keeps us out of suspend
);
always @(posedge usbclock)
begin
if (resetturnaround)
turnaround <= 1'b0;
else if ((cntrst == CNTRINACTIVE) && (cyclecount == MAXTURNAROUND))
turnaround <= 1'b1;
if (resetturnaround)
oktoxmit <= 1'b0;
// used to be I'd wait two clocks, but since our internal flops put us
// a clock behind the bus, lets say ok right away
//else if ((cntrst == CNTRINACTIVE) && (cyclecount != 1'b0)) // 2 clocks - 1 here, plus 1 till it goes active
else if (nextcntrst == CNTRINACTIVE) // if we see it going inactive, its ok to send
oktoxmit <= 1'b1;
else
oktoxmit <= 1'b0;
if (resetse0reset)
se0reset <= 1'b0;
else if (se0reset && (cntrst == CNTRSE0)) // once triggered, keep it until SE0 goes away
se0reset <= 1'b1;
else if ((cntrst == CNTRSE0) && (cyclecount == MAXSE0))
se0reset <= 1'b1;
end
always @(posedge usbclock)
begin
if (resetsuspend && resetturnaround && resetse0reset)
cyclecount <= 1'b0;
else
cyclecount <= cyclecount + 1'b1;
end
// state machine for counting weird cycles
always @(posedge usbclock)
begin
cntrst <= nextcntrst;
end
always @(cntrst or syncreset or cyclecount or syncidle or syncse0 or xmitactive or vpin or resumen)
begin
if (syncreset)
begin
nextcntrst = CNTRIDLE;
resetturnaround = 1'b1;
resetsuspend = 1'b1;
resetse0reset = 1'b1;
end
else
case (cntrst) // synopsys parallel_case full_case
CNTRIDLE:
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
resetse0reset = 1'b1;
if (xmitactive)
nextcntrst = CNTRACTIVE;
else if (syncse0)
nextcntrst = CNTRSE0;
else if (syncidle)
nextcntrst = CNTRINACTIVE;
else
nextcntrst = CNTRIDLE;
end
CNTRINACTIVE:
begin
resetse0reset = 1'b1;
if (cyclecount == MAXINACTIVE)
begin
resetturnaround = 1'b0;
resetsuspend = 1'b0;
nextcntrst = CNTRSLEEP;
end
else if (xmitactive)
begin
resetturnaround = 1'b0;
resetsuspend = 1'b0;
nextcntrst = CNTRACTIVE;
end
else if (syncse0)
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
nextcntrst = CNTRSE0;
end
else if (syncidle)
begin
resetturnaround = 1'b0;
resetsuspend = 1'b0;
nextcntrst = CNTRINACTIVE;
end
else
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
nextcntrst = CNTRACTIVE;
end
end
CNTRACTIVE:
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
resetse0reset = 1'b1;
if (xmitactive)
nextcntrst = CNTRACTIVE;
else if (syncse0)
nextcntrst = CNTRSE0;
else if (syncidle)
nextcntrst = CNTRINACTIVE;
else
nextcntrst = CNTRACTIVE;
end
CNTRSE0:
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
// can't really be here and have xmitactive
if (syncse0)
begin
nextcntrst = CNTRSE0;
resetse0reset = 1'b0;
end
else if (syncidle)
begin
nextcntrst = CNTRINACTIVE;
resetse0reset = 1'b1;
end
else
begin
nextcntrst = CNTRACTIVE;
resetse0reset = 1'b1;
end
end
CNTRSLEEP:
begin
resetturnaround = 1'b1;
resetsuspend = 1'b1;
resetse0reset = 1'b1;
// can't really be here and have xmitactive
if (~vpin || ~resumen)
nextcntrst = CNTRACTIVE;
else
nextcntrst = CNTRSLEEP;
end
endcase
end
// make the ascii version of the cntr state
// synopsys translate_off
reg [8*15:1] cntrstate;
always @(cntrst)
case (cntrst)
CNTRIDLE : cntrstate = "CNTRIDLE";
CNTRACTIVE : cntrstate = "CNTRACTIVE";
CNTRINACTIVE : cntrstate = "CNTRINACTIVE";
CNTRTURNAROUND : cntrstate = "CNTRTURNAROUND";
CNTRSLEEP : cntrstate = "CNTRSLEEP";
CNTRSE0 : cntrstate = "CNTRSE0";
endcase
// synopsys translate_on
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -