INSTANTIATED IN HARDWARE IN ORDER TO SEE CALIBRATION LED LIGHT
As evidence that I have everything working on the DDR3 memory, even though I haven't simulated successfully, I instantiated my entire project and loaded it onto the Arty A7 board. It is set up to light one of the four LEDs when the init_calibration_done signal is asserted, which will validate that all the clocking and reset and other basics are correct.
The light went on! I have working RAM now. The logic won't move on from that initialization because the design depends on reasonable inputs from an actual Diablo disk drive, which is not yet connected, but I did gain a bit of confidence from this simple test. If I set the switch to the upload direction and push the button, I saw the USB activity LED flashing.
I connected to it via a terminal program to see what comes out when I push the button. The link is almost reliable but every once in a while the output looks a bit wonky. I will drop the data rate down from the 921,600 baud of the module I borrowed to 460,800 or 230,400 or 115,200 which increases the upload time to as much as 15 1/3 minutes at the slowest speed.
CHANGED TIMING VALUES FOR THE UART BUT STILL COMING OUT AT 921,600 BAUD
I changed the VHDL for the modules involved but the data continues to stream out at the same old rate. This ultimately was due to the tendency of Vivado to work with cached versions of things. I was able to get it working at 115,200 which allowed me to move forward to check out the upload results.
BACK TO SIMULATION TO WORK ON DRAM CONTROLLER LOGIC
Grrrr. The FIFO simulations are completely absurd. I have two FIFOs, one with a data count on the write clock side and one with a data count on the read clock side. The write clock count goes up when I have only pulsed the other FIFO and not this one. The second time I pulse the r-FIFO, the rd count does go up, but the first was lost with the spurious w-FIFO write count increment. Most absurdly, a single pulse would not have the FIFO jump from 0 to 2 words.
Instead of two types of FIFOs, one with read count and one with write count, I created a common type that had both types of counts. My logic only looks at the read count from w-FIFO and the write count from r-FIFO, but both are there and under different signal names.
It still behaves bizarrely. I dug through the documentation for the FIFO and discovered that for the "accurate count" option I selected, if the FIFO is empty when the first word is pushed in, the counts won't be accurate. Other conditions produce inaccurate counts as well.
Since my FIFOs are fall-through, where the word pushed in becomes visible to the reading side before a read is issued, I have a different way to check. The valid flag should rise when a valid word is present, due to fall-through. That is what I will use to drive my logic.
The simulation of FIFOs built on distributed RAM failed to work properly, but when I switched to the native FIFO hardware everything did work as expected. After the simulation, I had all my read and write signals optimized.
Synthesizing for real hardware showed me that the damned toolkit insisted on using cached versions of the FIFOs even though I had changed parameters when I created them with the IP tool. I had to keep changing names to stop this since no commands would actually force the idiot software to do an actual generation again. Even that was foiled as the toolchain saw the similarity. Eventually I had to delete the cache file manually and restart the toolchain.
MEMORY INTERFACE SHUTTING DOWN RAM CHIPS DURING SIMULATION
One interesting thing I observed with the earlier simulations was that at some point, the memory interface turned off the RAM chips using signal ddr3_cke which I believed was a response to something being wrong with the memory configuration. However, when testing the write logic I noticed that if I did multiple writes without a long time between them, the ddr3_cke line seemed to stay high. I tested it with more activity and it will still stop about 900 uS after the initial calibration completes.
To see if this occurs in real hardware, I set up my test on the physical Arty A7 board, wanting to use the ddr3_cke signal to drive one of the LEDs. If it winks out while I am reading data, then there is an issue I have to resolve, otherwise it is just a limitation in the simulation. Unfortunately, this is an output buffer deep inside the memory interface IP and thus I can't read or sense it from within my logic. Nothing in the defined user interface shows me whether this signal went low due to some error state. In fact, there is no signal to indicate an error state.
I dug through the smallest nits in the messages during the creation as well as searched the paucity of examples for user interface access. Most people who use the MIG are using the memory with a soft processor that they instantiate, thus they go with the more cumbersome and complex AXI interface that the Blaze processor requires. I made changes, changing clocks, as well as switching the power-saving logic that was designed to throttle down power usage while the RAM wasn't being actively used.
From the detailed simulation capture the last activity I see before the memory interface shuts down is when it is attempting a refresh of the DRAM. The charge on the capacitors in DRAM decays rapidly thus it must be rewritten in the background to retain memory contents. The memory interface is responsible for this, interleaving actual user access to memory with these refreshes.
However, it was the handling of the first read request that appears defective. Internally the memory is 2Gb organized into 16 bit groups accessed by a row and a column address. Further, the interface is designed to grab eight consecutive words in each access (128 bits) thus we would have eight groups read out for an access. Below is what I see for the first read access:
Following that is a subsequent read access with only receives four groups not consistent with the "Burst Length 8" design of the interface. Note that one of the signals shows invalid values, meaning it is either driven by more than one source or not driven at all, not even hi impedance (Z).
Something is screwy with the behavior right with the first access, leading to the interface shutting down. This is a lovely world for logic designers using these toolchains, where you have to wade through miles of debugging of other people's work before you can debug an inch of your own work.