I discovered that the toolchain had become confused with a change I made inside the process that spits out the dummy data stream to test reading. I have an array of about 350 words of data that represent the contents of a disk sector, clocking them out one bit at a time until a 16 bit word is exhausted and then advancing to the next word.
It had worked fine, but I wanted to reverse the polarity of the bit being emitted since the disk drive delivers inverted data. I did this with a variable inside the process, which should work fine but the toolchain blithely claimed that my array of data was used but never assigned. It is assigned as an initial value on the signal declaration, however it forgot that and gave it the default value thus always 0.
Took a several hours of fighting with the toolchain before it would do what I asked and deliver the data stream I had initialized into the block ROM. I can't do anything until it begins emitting the pattern I set up. I tried many methods, finally extracting the relevant logic into a separate module that I could easily simulate to discover exactly WTF is going wrong.
The extracted logic simulated fine and is purely combinatorial. I instantiated it into the main logic and synthesized everything to test once again. It again failed to work. I even output the signal on a separate pin just to validate that I didn't have a dead output line, but the results were the same.
Tomorrow is the holiday (July 4), when I will be mostly busy with family, but I will do one last synthesis to output the states of the driver logic that extracts my dummy date. Then when I resume I can get to the bottom of this.