I have a digital receiver module needed in a MicroBlaze system that I coded in Verilog. The module is responsible for accepting, parsing, and storing receive data from a part our company makes. The part is responsible for driving the clock and data at 26 MHz. Our internal clock on our MicroBlaze embedded system is 38.4 MHz.
I desinged the block as two separate modules. The first module is basically a shift register that clocks in the serial data from the part when an enable line goes high (also driven by the external part). This module works in the 26 MHz clock domain. The second module is a state machine that accepts 96-bit chunks of data from the previous module, parses that data based on the format being sent (a MBlaze software register setting), and stores it in 32-bit chunks in internal block ram. This module works in the 38.4 MHz clock domain.
So the part sends the enable signal and that tells the 26MHz shift register to start clocking in data. After 96-bits are received, the module sends a trigger to the state machine logic. The state machine is in a WAIT condition - having already intitalized the data format via a software write. The state machine grabs the 96-bit chunk, parses it into 1 or 2 32-bit chunks (depends on format), discards the rest, and stores the data in block RAM.
I threw it in our MicroBlaze project, built the design, and started testing. I have a pattern generator set up to simulate the protocol that the extrenal part will be responsible for providing (our part is in fab). I have to use the EDK software debugger in order to see the data stored to memory. Everything appeared to be working fine. However, after increasing the data in the pattern, it was obvious that random errors were occuring in the data stored to RAM. There would occassionlly be incorrect values stored. I had the data coming in as a binary count and sometimes the count would glitch. It didn't occur often, but we can't have any errors.
So, I tried two things. The first was to put some synchronization flip flops in the state machine. Initially I had my concerns about crossing clock domains, but since I was going from a slower one to a faster one I didn't worry much. I put a couple each for the data being passed from the 26 MHz clock domain, and for the trigger being passed from the
26 MHz clock domain. After building this, the problem still occurred.I then put a KEEP_HIERACHY constraint on the top level module that instantiates the two modules discussed. Low and behold, that worked. I have tested extensively and there have been no errors.
Does anyone have any insight into why keeping the hierarchy intact works? I always try to design correct hierarchies in my modules...meaning hierarchy that makes sense. And all signals are registered at module boundaries. To me, the design discussed above is well-partitioned. I don't know what XST would "optimize" when the KEEP_HIERACHY was NOT specified. Just curious if anyone had any input.
I didn't check to see what area penalties, if any, occured after placing the constraint. I doubt it would make much difference.
Thanks!