.
.
.
reg [1:0] hbstate=2'b00, vbstate=2'b00; //initialise states to 0
reg reset_db=0; //initialise reset to 0
integer hbcnt=0, hbbootcnt=0, vbcnt=0, vbbootcnt=0, watchdog=1000000; //counters, values initialised as required, 1000000 for watchdog = 10ms
always @ (posedge clock) //FPGA clock
begin
watchdog<=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 timer
else 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 reset
begin
reset_db<=1; //turn on reset
if(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)
begin
watchdog<=1000000; //set watchdog timer to 10ms again
reset_db<=0; //turn off reset
end
end
end
always @ (posedge ps2_vclk) //device clock
begin
if(reset_db==1) //if reset is equal to 1, reset all counters and status' as below
begin
hbstate<=boot;
hbcnt<=0;
hbbootcnt<=0;
vbstate<=boot;
vbcnt<=0;
vbbootcnt<=0;
end
.
.
.
.
.
.
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)
begin
watchdog<=watchdog+1;
case(wdstate)
boot : begin
if (ps2_hblank==1 && watchdog<=1000000) watchdog<=0;
else if(watchdog>=1000001) wdstate<=start;
end
start : begin
reset_db<=1;
if(hbstate==boot)
begin
wdcnt<=wdcnt+1;
if(wdcnt>=75000000)
begin
watchdog<=0;
wdcnt<=0;
reset_db<=0;
wdstate<=boot;
end
end
end
endcase
end
always @ (posedge ps2_vclk)
begin
if(reset_db==1)
begin
hbstate<=boot;
hbcnt<=0;
hbbootcnt<=0;
vbstate<=boot;
vbcnt<=0;
vbbootcnt<=0;
end
case(hbstate)
.
.
.
Sure. The code implements a handshake synchronisation mechanism, unfortunately without sync registers for the handshake signals. This kind of design flaw isn't necessarily detected in simulation.1) You have two blocks using two different clocks. Is there a CDC issue?
I do not see any "if" that can cause latches. All "if"s I see are in clocked always blocks, and they create FFs with clock enables hold the value of the signals when the condition is not satisfied.2) Your If/elsif statements have some undefined conditions which will probably create latches.
localparam WATCHDOG_10MS_COUNT_VALUE = 1000000; // @ 100MHz
always @ (posedge clock)
begin
if(reset_db==0) begin
watchdog<=watchdog-1;
if(ps2_hblank==1) watchdog<= WATCHDOG_10MS_COUNT_VALUE;
else if(watchdog==0) reset_db<=1;
end else begin
reset_db<=1;
if(hbstate==boot)
begin
watchdog<= WATCHDOG_10MS_COUNT_VALUE;
reset_db<=0;
end
end
end
I’m not really a Verilog guy, but several things jump out at me.
1) You have two blocks using two different clocks. Is there a CDC issue?
2) Your If/elsif statements have some undefined conditions which will probably create latches.
3) Have you simulated this? That will tell you a lot.
Sure. The code implements a handshake synchronisation mechanism, unfortunately without sync registers for the handshake signals. This kind of design flaw isn't necessarily detected in simulation.
I believe, the watchdog function can be coded safe and also readable and straightforward.
I do not see any "if" that can cause latches. All "if"s I see are in clocked always blocks, and they create FFs with clock enables hold the value of the signals when the condition is not satisfied.
@Mario875 I do not see any errors in the part of the code you showed, except for the absence of CDC synchronizes. See, for example, https://www.eetimes.com/understanding-clock-domain-crossing-issues/
I suspect that the error in the part of the code you didn't show. There might be not all signals reset in your reset statement of the second always block (and why you repeat the same code twice there?). With the current watchdog logic, your reset is set for a brief moment, and the signals not mentioned in the reset block might stay not cleared. While when you press the button, it is very long event and the signals not covered by the reset are somehow cleared by themselves while the button is still pressed.
--- Updated ---
It's kinda unrelated, but the first always block is overcomplicated, hard to read, and uses more resources than it should. Also, what happens when ps2_hblank==1 && watchdog<=0 ?
The watchdog can go negative, and it is defined as an integer. This forces it to 32 bit width. You don't really need negative values at all.
Consider the following code:
Code:localparam WATCHDOG_10MS_COUNT_VALUE = 1000000; // @ 100MHz always @ (posedge clock) begin if(reset_db==0) begin watchdog<=watchdog-1; if(ps2_hblank==1) watchdog<= WATCHDOG_10MS_COUNT_VALUE; else if(watchdog==0) reset_db<=1; end else begin reset_db<=1; if(hbstate==boot) begin watchdog<= WATCHDOG_10MS_COUNT_VALUE; reset_db<=0; end end end
It's not only clearer, but you can redefine watchdog counter to be positive only and also use less bits as it never leaves [0, 1000000] range.
Also you don't need to repeat in English what is already written in Verilog. Not a single comment in the code you posted adds any understanding to the code.
reg reset_db=0; //initialise reset to 0
reset_db<=0; //turn off reset
Anyone can see that you assign 0 to the reset signal without these comments. Comments are needed when you need to communicate some information that you cannot communicate in Verilog/VHDL/other PL.
Hi,
Let's think outside the box a little bit. We have the .sof file and the .pof file. Which one did you program the FPGA with?
Yes, you're right. I was thinking it might have to do with file-dependable volatile and non-volatile programming that can be read up here https://techniex.com/creating-and-configuring-xilinx-fpga-with-mcs/ but it's not since it works with your reset_db signal pushbutton. It's more than likely an FSM issue. I don't understand verilog but could I ask if you could see the state diagram for the code?...
FPGA is programmed with a .bit file and .ltx files for the debug probes in Vivado, not .sof or .pof files...
if(hbstate==boot)
begin
watchdog<=1000000;
reset_db<=0;
end
Yes, you're right. I was thinking it might have to do with file-dependable volatile and non-volatile programming that can be read up here https://techniex.com/creating-and-configuring-xilinx-fpga-with-mcs/ but it's not since it works with your reset_db signal pushbutton. It's more than likely an FSM issue. I don't understand verilog but could I ask if you could see the state diagram for the code?
A CDC problem is brought up if an asynchronous variable controls the assignment of multiple bits.
e.g. in this code snippet, when hbstate is asynchronous (originated from a different clock domain), it's not guaranteed that all bits of variable watchdog are set in the same clock cycle. The temporary state may cause unexpected reaction of other logic parts. State machines can be even caught in an endless illegal state.
Code:if(hbstate==boot) begin watchdog<=1000000; reset_db<=0; end
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?