Why is this Verilog Code not working as expected?! - Page 1
Forum section: electronics / general

author: Mario87
author_rank: Frequent Contributor
timestamp: October 09, 2022, 02:30:35 pm
content: Hi all,I have created come verilog code to lock onto the output signal of a device and make a new signal with a greater pulse width. Now when I have the device powered on and I program the FPGA it locks on 100% of the time, no issues.However, if I reset the device, but do not re-program the FPGA, I lose the lock (as expected), so I created a 'watchdog' reset that will essentially reset the IP and allow it to re-lock again. If I attach the 'reset_db' signal to an external push button, it works perfectly in that resetting the device loses the lock, but when I press the push button, the IP resets and re-locks as expected.I thought, that's great, now let me try and automate the reset with a watchdog timer, code (with comments) below, and the strange thing is that when I simulate it, the code works as expected, but when I implement it, it just doesn't, almost as if some of the counters or states are not being properly reset.Essentially the watchdog is clocked by the FPGA 100MHz clock and if the device is enabled, one of the signals resets the watchdog every 100us, but when the device is reset the signal will go low for 500ms and the watchdog timer is set to only 10ms, so when that happens the FPGA should hold the reset value high, then when the device comes back on and reset is held high, all states and counters will be reset, once that happens (hbstate==boot) then the reset signal is asserted low and the watchdog counter reset for it to repeat.It just doesn't work and the output signals end up totally out of sync, but when I use a push button to manually reset instead of the watchdog counter, it works as expected??Any thoughts / ideas??Code:...reg [1:0] hbstate=2'b00, vbstate=2'b00; //initialise states to 0reg reset_db=0; //initialise reset to 0integer hbcnt=0, hbbootcnt=0, vbcnt=0, vbbootcnt=0, watchdog=1000000; //counters, values initialised as required, 1000000 for watchdog = 10msalways @ (posedge clock) //FPGA clockbeginwatchdog<=watchdog-1;if(ps2_hblank==1 && watchdog>=1) watchdog<=1000000; //if signal from device is present (square wave with 100us period) and watchdog is present, reset watchdog timerelse if(ps2_hblank==0 && watchdog<=0) //if signal is lost (drops for 500ms during a reset), and watchdog counter is less than or equal to 0 (10ms has elapsed), begin the resetbeginreset_db<=1; //turn on resetif(hbstate==boot) //if 1 of the states has reset (indicating the device has powered back on, as it is reliant on the devices own clock)beginwatchdog<=1000000; //set watchdog timer to 10ms againreset_db<=0; //turn off resetendendendalways @ (posedge ps2_vclk) //device clockbeginif(reset_db==1) //if reset is equal to 1, reset all counters and status' as belowbeginhbstate<=boot;hbcnt<=0;hbbootcnt<=0;vbstate<=boot;vbcnt<=0;vbbootcnt<=0;end...

author: pcprogrammer
author_rank: Super Contributor
timestamp: October 09, 2022, 03:19:01 pm
content: I might be wrong but "integer" might not work in the actual device. Try using properly sized "reg" instead. (reg [31:0] watchdog = 1000000;)QuoteTaken fromhttps://verilogguide.readthedocs.io/en/latest/verilog/datatype.html

author: Mario87
author_rank: Frequent Contributor
timestamp: October 09, 2022, 08:14:08 pm
content: Hi, I do not think the integer is an issue to be honest as I am using integer for all the other counters and they work fine, however I am admittedly using them to count up, not down, so no negative numbers required.I have modified the code as below, even adding a 750ms wait after hbstate changes to 'boot' but still the exact same issue. However, when I comment out the code in the 1st always block and use a push button to enable reset_db, it works fine?!Code:...reg [1:0] hbstate=2'b00, vbstate=2'b00, wdstate=2'b00;reg reset_db=0;integer hbcnt=0, hbbootcnt=0, vbcnt=0, vbbootcnt=0, watchdog=0, wdcnt=0;always @ (posedge clock)beginwatchdog<=watchdog+1;case(wdstate)boot : beginif (ps2_hblank==1 && watchdog<=1000000) watchdog<=0;else if(watchdog>=1000001) wdstate<=start;endstart : beginreset_db<=1;if(hbstate==boot)beginwdcnt<=wdcnt+1;if(wdcnt>=75000000)beginwatchdog<=0;wdcnt<=0;reset_db<=0;wdstate<=boot;endendendendcaseendalways @ (posedge ps2_vclk)beginif(reset_db==1)beginhbstate<=boot;hbcnt<=0;hbbootcnt<=0;vbstate<=boot;vbcnt<=0;vbbootcnt<=0;endcase(hbstate)...

author: agehall
author_rank: Frequent Contributor
timestamp: October 10, 2022, 02:12:26 pm
content: To me it looks like hbstate is always boot which means that your reset signal will always be 0. At least in the original code you posted.I’d advise you also simulate it to see what is happening.

author: Mario87
author_rank: Frequent Contributor
timestamp: October 13, 2022, 03:08:23 pm
content: Quote from: agehall on October 10, 2022, 02:12:26 pmHi, hbstate can't be stuck on 'boot' otherwise I would get no signal at all and that is not my issue, my issue was that the signal was out of sync. As I mentioned it works fine when simulated and when I use a push button to reset.In the end I found out the problem, well 2 problems actually. A CDC issue and a quirk of the device I am trying to lock onto.I separated the watchdog into its own IP and used the Xilinx XPM CDC IP block to join the 2 together, this was certainly required, but it was not the only issue. Turns out when I reset the device, even though its clock came back in 500ms, I could not get a good lock unless I waited a good 3-4 seconds! Once I figured this out I did try reverting back to my original design just to test, but it would not work again (unsurprisingly), so the CDC issue was definitely a problem, but then this quirk of the device was not helping, and hence it would work fine when using a push button as I always rebooted the device and waited a few seconds before pressing the button.All is well now and it is working pretty reliably. I can occasionally trip it up and it ends up about 8500 clock cycles out, but if I reset again, it works fine. Think I just need to tweak the timing a bit.