On 5/30/06, Petter Urkedal <[EMAIL PROTECTED]> wrote:
I looked a bit on this in the weekend, but since have no experience I
didn't want volunteer to lead it. You can see what I have got this far
on
http://85.235.225.158/~petter/ogp/spi_prom/
I have, however, made an assumption that, after reading your post, I
think is wrong. If you'll excuse the elementary question:
When reading some Verilog tutorial, I drew the conclusion that there is
an underlying assumption about flip-flops and timing. Namely, that
there is a delay from when the data is sampled at the rising clock until
the data appears on the output. Furthermore, this delay is longer than
the variance in sampling times due to propagation and finite rise-time
of the clock signal. Thus, the same clock can drive serially connected
flip-flops, and the data is sampled at the end of the duration of their
valid value.
This is correct.
This is not the case for the PROM, right? I can think of some reasons
why not:
* It uses different tech. than the FPGA, and thus sample that data
at different points on the rising clock edge.
* It may drain more charge than is available at the end of the valid
cycle.
Mostly it comes down to there being propagation delays on all of the
external I/O signals.
(Since the PROM inputs on posedge and outputs on negedge, we could force
the assumption by shifting the clock of the PROM by pi/2 before that of
the controller. This should work for reading to, since the PROM outputs
on falling clock:
clk: ++++----++++----++++----++++----++ + high
sck: ++----++++----++++----++++----++++ - low
SI: XDDDDDSDXDDDDDSDzzzzzzzzzz X indefinite
SO: zzzzzzzzzzzzzzzzzzXDDDDDSDXDDDDDSD D data, S sampled data
Or is it's critical to hit the middle of the valid data?)
It's simply more convenient to hit it in the middle. So, the SCK is
180 degrees (PI) out of phase from our internal clock. Or at least
that's how we're generating it, but the I/O buffers will add some
nanoseconds here and there.
But, the timing-assumption holds within the FPGA, right? So, we don't
have to deal with such detailed timing considerations for most of the
work?
Exactly.
Some more specific questions:
Is clock_1x the full FPGA clock or the PROM clock? FPGA is 200 MHz,
right? So, maybe 1:16 for the PROM? Or go with fast read only and use
1:8?
clock_1x is sortof a typo from copy/paste from other code. We'll use
only one clock and generate SCK using a DDR flipflop.
Here's a quick and dirty simulation model (won't synthesize) of a DDR
I/O buffer:
module DDRIOFF(clock_p, clock_n, in_p, in_n, out);
input clock_p, clock_n, in_p, in_n;
output out;
reg out;
always @(posedge clock_p) out <= in_p;
always @(posedge clock_n) out <= in_n;
endmodule
We have positive and negative clocks and two data inputs, one for the
high cycle and one for the low cycle.
Instantiating it will look like this:
DDRIOFF ddrbuf (.clock_p(clock), .clock_n(!clock), .in_p(...),
.in_n(...), .out(...));
In our case, with the phasing and all that, I think it would look like this:
DDRIOFF ddrbuf (.clock_p(!clock), .clock_n(clock), .in_p(sck_enable),
.in_n(0), .out(...));
I might not have that exactly right.
Reading your previous post, it seems that you only intend to support
byte writes, i.e. only one bit in write_bytes is set for each write.
Is that right? (My sketch takes any value of write_bytes, but this
conflicts with configuration.)
Right. The basic problem is that it's evil to cause unnecessary wait
states on the PCI bus. When you do, you starve other devices. Since
it's milliseconds between writes (required by the SPI), we can just
let software time the delay.
And with write_bytes == 'b1111, we're using that as metadata to say
that we're not writing data but sending a command.
Don't bother checking if the write_bytes is valid. Assume it is. If
it's wrong, the results are undefined, but it's programmer error.
Here's the conversion:
assign addr[1] = write_bytes[3] || write_bytes[2];
assign addr[0] = write_bytes[3] || write_bytes[1];
Actually, I've been thinking little-endian, so in fact, we may have to
reverse the order. We can make it selectable by supplying a two-bit
XOR mask:
wire [1:0] swapped_addr = addr[1:0] ^ swap_mask;
Better yet, we can let software handle the byte ordering by fiddling
with the address in the CPU. Like I say, we've got milliseconds.
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)