One of the first few items in the checklist for a failing testcase is the clock to the module. Usually an external crystal oscillator would be fed into a PLL block within the SoC to obtain and supply derivative clocks to all other parts of the system. So if a peripheral module does not respond when its control registers are being read it would be helpful to check if the clocks to the module are running and are of the correct frequency along with top level connections.
I came across a scenario where the test was trying to read reset values from the peripheral control registers and it almost passed except for a single register that reported an X. After doing a basic debug routine by pulling up the waveform tool, I realized that the clock to the module was a 0 -> X -> 0 -> X pattern. The simulation tools consider a transition from 0 -> X as the posedge of the signal, and hence
always blocks must have behaved as though it was a 0 -> 1 transition. Sometimes gated clocks can have such problems, and will be more evident during gate level simulation. Here's a small example of achieving a similar effect.
module tb; reg clk; reg gatedClk; reg gateEn; always #10 clk = ~clk; initial begin clk = 0; #100 $finish; end assign gatedClk = gateEn && clk; always @ (posedge gatedClk) $display ("I am active even on a 0->X transition"); endmodule
It'll be useful to have checkers and assertions to verify that clocks to every block are of the correct frequency and have valid states.
vsim> run I am active even on a 0->X transition I am active even on a 0->X transition I am active even on a 0->X transition I am active even on a 0->X transition I am active even on a 0->X transition Simulation complete via $finish(1) at time 100 NS + 0