Forum Discussion
Altera_Forum
Honored Contributor
21 years agoWell, it sounds like all you need for recovery time is a counter that counts down to 0 and then stops, which gets triggered (loaded) after an access. Then, when a new access comes in, if that counter isn't 0 yet, you assert waitrequest.
Here's some Verilog code that shows what I'm getting at. I can't guarantee this code, because I haven't tested (or even compiled) it. This also doesn't properly handle the case where one or more of the delay constants is 0, and it might stuff in an extra clock. There are also various failure cases (Avalon bus aborting the transfer?) that aren't taken into account, so caveat programmer...module USBInterface
(
// From Avalon bus. All are active high.
input clk,
input reset,
input read,
input write,
input chipselect,
output reg waitrequest
);
// Timing values, in CPU clocks.
localparam kReadWaitStates = 2; // I'm making all these numbers up.
localparam kWriteWaitStates = 4; // Set them to realistic values.
localparam kReadRecoveryClocks = 20;
localparam kWriteRecoveryClocks = 60;
wire doRead, doWrite;
assign doRead = read & chipselect;
assign doWrite = write & chipselect;
// Delay counter
reg delay, newDelay; // or however many bits you need.
reg start;
always @(posedge clk, posedge reset)
if(reset)
delay <= 0;
else if(start)
delay <= newDelay;
else if(delay > 0)
delay <= delay - 1;
// State Machine
reg accessState, nextState;
localparam sIdle = 0;
localparam sWaiting = 1;
localparam sActive = 3;
localparam sRecovering = 2;
always @(posedge clk, posedge reset)
if(reset)
accessState <= 0;
else
accessState <= nextState;
always @* begin
// Defaults
nextState = accessState;
start = 0;
waitrequest = 0;
newDelay = 8'bxxxxxxxx;
// States
case(accessState)
sIdle: begin
nextState = sWaiting;
start = 1;
waitrequest = 1;
if(doRead)
newDelay = kReadWaitStates - 1;
else if(doWrite)
newDelay = kWriteWaitStates - 1;
else begin // Nothing to do, stand down.
nextState = sIdle;
start = 0;
waitrequest = 0;
end
end
sWaiting: begin
if(delay == 0)
nextState = sActive;
waitrequest = 1;
end
sActive: begin
nextState = sRecovering;
start = 1;
if(doRead)
newDelay = kReadRecoveryClocks;
else
newDelay = kWriteRecoveryClocks;
end
sRecovering: begin
if(delay == 0)
nextState = sIdle;
waitrequest = doRead | doWrite;
end
endcase
end
wire interfaceActive; // This goes high for one clock after the wait states expire.
interfaceActive = accessState == sActive;
endmodule