Hi Brad,
There is a FIFO overflow, I think. Let me explain wht I think I see:
When valid frame data is available (vframe_2 = '1'), you start saving data on the rising edge of the line indicator (vline1 = '1' AND vline_2 = '0'). Once the second line starts, you start reading out the FIFO. If a frame has H lines, you will have stored H lines, but only read out (H - 1)!
[ASCII graph, use fixed font] ______________________ ______________________ FRAME ___/ \___/ \___ __ __ __ __ __ __ LINE ______/ \___/ \___/ \_________/ \___/ \___/ \______ ___________________ ___________________ WRITE ______/ \______/ \___ ____________ ____________ READ _____________/ \_____________/ \___
The fix is to start reading out the FIFO at the same time as you start writing it, except for the very first line that you store (because you have to fill the FIFO with 1 line of data). You can use the same starting condition, except that you have to check the FIFO for not being empty before launching the reads. There are 2 possibilities to do this:
1) check the FIFO's empty flag
2) have a register that is reset along with the other registers and only set by the write enable (less resources if the FIFO hasn't the empty flag by default).
My next comment is on the robustness of your design: what happens when you switch on the video source or when you reset your design while the source is running? There is no reason you will start saving the data from the first line in a frame: if you see the 3th line pulse in a frame first after reset, the you will currently start storing there. The solution is to have an additional enable register that is reset like the others and is set when frame is low: as such, no line will be stored before you have seen frame going low.
Combining my remarks should give you the following waves:
[ASCII graph, use fixed font] ___ RESET \_____________________________________________________________________ _______________ ______________________ ______________________ FRAME \___/ \___/ \___ __ __ __ __ __ __ __ __ LINE __/ \___/ \_________/ \___/ \___/ \_________/ \___/ \___/ \______
________________________________________________________ FRMen+ ________________/ ___________________ ___________________ WRITE ______________________/ \______/ \___
_________________________________________________ nEMPT+ _______________________/ ____________ ___________________ READ _____________________________/ \______/ \___
Summarised: WRITE start at the first line of a frame READ start at the first line of a frame that the FIFO is not empty
If you're still up to some comments: the delay of the signal driving the mux of vin_3 and the "10101010" constant puzzles me: assuming 1 cycle delay between fiforden and the data coming out of the FIFO, then vin_3 and fifodout are nicely aligned. But you add 2 more delays in process v5 by using video_bits_2. Is this what you need (you're shifting the decision 2 pixels)? Likewise, when you're checking for the treshold of the lines (current - 2) and (current - 3), did you consider the wrapping from the bottom line to top line in the next frame?
Some very last suggestion: do you check the timing of your asynchronous reset? Without a flipflop clocking this signal, you will have no control over it and you risk all kind of trouble (meta-stability when violating setup/recovery timing of the resetable flipflops, flipflops coming out of reset in a different clock cycle). In an FPGA, it's safer to use a synchronous reset and it won't cost you any more resources (see the FPGA registers).
Kind regards, Alvin.