On 6/6/06, Petter Urkedal <[EMAIL PROTECTED]> wrote:
On 2006-06-05, Petter Urkedal wrote:
> Well, as soon as the client gives an instruction other than a re-fetch
> from the same address, read_out_valid goes low on the next cycle.  But,
> you probably mean that read_out_valid must only be asserted for one
> cycle after busy goes low.  I think, in fact, Howard's code did that,
> but out of maybe a maybe foolish eagerness to optimise, I didn't
> introduce the extra reg to do that.
> >> Some notes:
> >>
> >>   * In the test case of your orginial post, you wrote
> >>
> >>         do_read = 1;
> >>         while (busy) #20;
> >>         #20;
> >>
> >>     I assume this should be
> >>
> >>         do_read = 1;
> >>         #20;
> >>         while (busy) #20;
> >
> > You might be right.  I have to think about it.  The protocol is a bit
> > weird and best expressed with synchronous logic.
> >
> > If busy=0, and you want to send something (a read command), you pulse
> > do_read for one cycle.  If busy=1, you assert do_read and hold it
> > until one cycle after busy goes away.  Requests are transferred only
> > on cycles where busy=0.
> That makes sense, and read_out_valid actually comes to use in the test case:
>
>     do_read = 1;
>     while (busy) #20;
>     #20;
>     while (!read_out_valid) #20;
>     // read_data is valid here

Parethetical, just to elaborate on this:
    I used 'while (busy) #20' to wait for read data to become available,
    assuming the client respected timing for writes, and always waited
    for reads to finish so that we were never busy on a new request.
    Dropping that assumption, I could have written

        do_read = 1;
        while (busy) #20;
        #20;
        do_read = 0;
        while (busy) #20;
        // read_data available

    OTOH, if we drop busy, as you indicated we might, I think the fetch
    sequence is

        do_read = 1; // assuming device is not busy
        #20;
        while (!read_out_valid) #20;
        // read_data is valid;

    which is basically the same as 'do_read = 1; #20; while (busy) #20;'.

This is making my head hurt.  I don't know why.  :)

Ok, let's see....

If busy is low and the the read is a hit, this is what we would see on
a waveform viewer:

do_read = 1;
#20;
do_read = 0;
read_valid = 1;
#20;
read_valid = 0;

That's simple enough.  The request pulses, and one cycle later, the
valid pulses.

---

If busy is low, but we get a read miss, this is what we see:

do_read = 1;
#20;
do_read = 0;
busy = 1;
#(20 * n);
busy = 0;
read_valid = 1;
#20;
read_valid = 0;

The rule is that the request is accepted if busy is low, which is why
it goes away after only one cycle.  And if busy is high, the request
is completely ignored (so it's safe to make it regardless of the state
of busy).  This the usual logic that implements this:  [Not really;
this isn't right for like an address.  See below.]

always @(posedge clock) begin
   if (!busy) do_read <= 0;
   if (wanttoread) begin
       do_read <= 1;
   end
end

Logically, it's the same as this:

always @(posedge clock) begin
   if (wanttoread) begin
       do_read <= 1;
   end else if (!busy) begin
       do_read <= 0;
   end
end

But I like to think of them as two separate things, and the ordering
of statements makes it work.

----

If busy is high when we want to make a request, this is what we see:

busy = 1;
...
do_read = 1;
#(20 * n);
busy = 0;
valid = 1;
#20;
do_read = 0;
...

What's happening here is that the request is being ignored until the
cycle when busy is going low.  That is, the logic as I wrote above
doesn't deassert do_read until after it's observed busy==0 for a
cycle.

The more complete logic for this, when you have to transfer data with
the request (like an address in this case) is like this:

always @(posedge clock) begin
   if (!busy) do_read <= 0;
   if ((!do_read || !busy) && wanttoread) begin
       do_read <= 1;
       read_addr <= whatever;
   end
end

And simplified (logically):

always @(posedge clock) begin
   if (!busy) do_read <= 0;
   if (wanttoread) do_read <= 1;
   if ((!do_read || !busy) && wanttoread) begin
       read_addr <= whatever;
   end
end



What is the requirement for read_out_valid?  You said that it should
only be asserted in respose to a read request.  Does it also need to go
low a cycle later, or could it remain high until a new request is made?


It would be best to make it go low one cycle later, I think.  We have
multiple sources of read data being given to the PCI controller, and I
think it might simplify things if we couldn't have more than one
'valid' signal asserted at the same time.  Technically, the data isn't
valid the instant we change the address to something else anyhow.
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to