I've actually taught the FPGA to do something useful now: I can send it commands via SPI (using the Aardvark to stand in for a microcontroller), and thereby set the timing of a 24-bit PWM generator (24 bits each for interval and pulse width), which sure enough puts out pulses from zero to DC high in 20 ns increments.
The SPI slave interface plus one channel of 24-bit PWM takes up 123 slices, or just about 5% of an XC3S250E.
So now I have a precision pulse generator... and adding burst-of-pulses capability would be trivial. That's a piece of test equipment that would have come in handy a couple of years ago (I ended up borrowing a nearly-capable pulse generator from the client for that series of tests).
Changing a constraint to call for a 100 MHz clock and recompiling gets, indeed, a design capable of 100 MHz operation, so pulses in 10 ns increments are possible with this standard-speed part and no extra cleverness (beyond figuring out how to use a clock manager, which is on the agenda for Real Soon Now).
I keep running into pesky snags, though.
Coding up the SPI slave interface as a pure behavioral model led to a series of incomprehensible error messages and logic that didn't do what I though I'd asked for. (It doesn't help that SPI uses both edges of the clock. I ended up relying on a high-frequency local clock.)
Sometimes, the compiler would apparently optimize out things that weren't optimize-outable, or fail to note that two conditional portions had contrary conditions (I had to combine them via elsif; checking for "a and b" in one place and "c and not b" in the other didn't tell the compiler that the two conditions were mutually exclusive).
Elsewhere, it seemed to be optimizing out logic based on what the state of a variable was known to have been going to be after the next clock... which doesn't seem quite legitimate, somehow, in clocked logic.
Oh, and once in a while I'll set ISE to implementing my top-level module, surf the net for a couple of minutes, and find that ISE Just Quit somewhere along the line. Restarting ISE and recompiling solves the problem. Eh? (Guess if I started it from the command line, I might see an error message when it terminated.)
Ah, well. I can do semi-useful things with VHDL now, and clearly there's much more to learn.
Update: I instantiated a clock manager, and tried a couple of different configurations... and clearly I still have much to learn. While the timing analyzer says I should be able to clock my design up to 114.something MHz, if I try to set the clock manager for 100 MHz I get timing errors (worst-case delay is shown as a bit under 9 ns, so I don't know what timing it's complaining about). If I change the constraints and tell the software that the input clock is only 25 MHz, it happily spits out a design that does run (at least, on this one device and at room temperature) just fine at 50 MHz in / 100 MHz internal clock.
Update 2: D'OH! In fact, I didn't tell the software that the input clock was 25 MHz. I told it that the minimum period was 20 ns, for 50 MHz, before it gets multiplied up.
The problem was that I'd previously changed the minimum period to 10 ns, without including the multiplier, just to see if the logic could run at 100 MHz. So, when I was getting all the timing errors, the software thought I was planning to run the innards at 200 MHz, which I wouldn't expect to work.
Recent Comments