Friday, April 23, 2010

Lattice DDR2 cores - read_data_valid doesn't come up...?

So as is usual, I'm suspicious of crummy simulation models and that's of course the reason why Lattice's ECP3 DDR2 (6.7 and 7.0 beta) cores don't give read_data_valid during simulation... They output the data, but not the read_data_valid signal.

After 2 hours of debugging, I found that it was all in the module hookup. read_tap_delay! The signal that they don't bother documenting, or explaining was causing the problem. I accidentally hooked up read_tap_delay to 2'b0 instead of 6'b0 (shame on me). This killed it. I guess I learn 2 things here, first that lack of documentation doesn't indicate lack of importance! and second that 2'b0 doesn't translate in all situations to fill the port with zeroes!

On the other hand, I finally took the plunge and hooked up Micron's DDR2 model. I have to say that it was the easiest model ever to hook up! Just define sg3 and x16 and voila, it's done. OK OK, there were two small snafus...

Lattice provides their cores with a simulation model, if you try to swap out their DDR2 model (also Micron's), then there is at least one problem. They have a file where they define x8 for all cores. I don't know why, I'd guess it's got something to do with Micron's old model. Anyhow for those of you swapping models for simulation, be aware of that. It will explain why Micron's model suddenly insists on a data bus of incorrect size even though you defined everything properly!

Lattice doesn't include negative differential ports in their top level definition, so if you have a clk_p and clk_n, all that appears in the top level netlist is clk_p, and the lpf file (constraints file) indicates the differential nature and automatically connects the differential pair. (Yes, pairs are fixed in the ECP3 and many other Lattice FPGAs.)

So now I have a DDR2 model requiring clk_n and dqs_n. clk_n is simple, just:
wire clk_n;
assign clk_n = ~clk_p;
easy shmeezy

On the other hand, dqs_n is an experience in learning. To save you the time that you've probably already spent trying to figure this out, here it is:
wire dqs_n;
assign dqs_n = (dqs_p === 1'bz) ? 1'bz : ~dqs_p;

Yes yes, the 3 equal signs are necessary. Shockingly a part of the language I'd never needed to use before, now comes in handy.

Live to learn another day,

No comments:

Post a Comment