As I stated in my comment,
mem is an inferred level-sensitive latch (for rest of the answer I will use latch for anything level-sensitive, and flop for anything edge-sensitive). Latches are inferred in always blocks that are not edge-triggered (
negedge) and is not assigned to a deterministic value if all logical branches.
Here is your original logic reformatted with my comments:
always @(data_trigger or reset) // <-- poorly inferred latch
if (reset) // Asynchronous reset because 'reset' is in the sensitivity list
for (n = 0; n < 10; n = n+1) mem[n] = 8'h00;
i = 0;
checksum_buff = 8'h00;
else if (data_trigger) // <-- Also asynchronous
if ( i < 10)
mem[i] = input_data;
i = i + 1; // <-- as a latch will cause feedback loop on FPGA, will not be detected on in Simulations
checksum_buff = input_data;
i = 0; // <-- also will cause a feedback loop to 'if(i<10)' in FPGA
Except for synchronous logic, synthesizers do not look at the sensitivity list. Therefore
i are actually part of the sensitivity list during synthesis. Simulation does use the sensitivity list, therefore it will ignore changes to
i. This is a place where simulation and synthesis will mismatch.
i is part of the real sensitivity and it is updated on every pass of the always block. This creates an asynchronous feedback will
data_trigger is high and
reset is low. If you were to have added
i to your sensitivity list, your simulation would likely hang from an infinite loop. On FPGA there is a slight propagation delay so you will results of seemingly random data. If you were measuring power you would also see high power consumption in this condition.
If you look through your log files there may be a warning about the asynchronous feedback.
i needs to be a flop.
checksum_buff should be flops too. From an eyeball review of your code, it looks like everything is running on the
posedge clk domain. Therefore I suggest you change the code to:
always @(posedge clk)
for (n = 0; n < 10; n = n+1) mem[n] <= 8'h00;
i <= 0;
checksum_buff <= 8'h00;
else if (data_trigger)
if ( i < 10)
mem[i] <= input_data;
i <= i + 1;
checksum_buff <= input_data;
i <= 0;
With this reset will also be synchronous. If you really want asynchronous reset, change it to
always @(posedge clk or posedge reset). If you really want
data_trigger to be the clocking event (I don't recommend it) then change the
posedge clk to
posedge data_trigger AND replace
else if (data_trigger) with
negedge signal referenced in the block is treated as an asynchronous trigger. You have this issue in your
Verilog combinational logic should be written in
always @* or the synonymous
always @(*). You will run into code that give a list of signals instead of a literal
*; don't do that. That style is for legacy Verilog-1995. Since Verilog-2001
@(*) is the preferred strategy to limit the risk an incomplete sensitivity list. The other thing for proper combinational logic is that each left-hand-side (LHS) signal must be assigned to a determinate value for all possible logic branches. Assigning it to itself doesn't count. Assigning it a determinate value at the top of an always block before an
case gives it a default assignment. Combinational logic should be assigned with blocking statements (
Synchronous logic must be have a clocking trigger
negedge. Do not reference the clock signal in the body of the of the always block. Up to two additional
negedge signals can be in the sensitivity list for asynchronous reset/preset, and asynchronous must assign registers to constants. Not all FPGAs support flops with asynchronous reset/preset; some have a limited number. Check the manual for your board. Synchronous logic should be assigned with non-blocking statements (
Latches usually should be avoided. Unfortunately they can be unintentionally inferred with what should be combinational logic. A latch happens when not all logical branches assign the signal to a deterministic value. If you need a latch, keep it logic simple and assign with non-blocking.
always @* begin
if (enable) Q <= D;
If you have SystemVerilog you can be more explicit by replacing
always @* with
always_latch. This way your synthesizer can do a better job warning you about unintentional latches.
FYI: Verilog non-blocking was inspired/copied form VHDL. The usage of blocking and non-blocking should be similar between the two.
The issue is that the keywords "posedge" and "negedge" in Verilog (or "rising_edge" and "falling_edge" in VHDL) have very special meaning to the synthesizer. The synthesizer gives every signal attached with these keywords a dedicated clock routing network on the FPGA. Do not use those keywords for any signal that you do not want connected to a clock routing network on the FPGA (which obviously, should be no signal other than a clock).
It is a great waste to use one of the precious few dedicated clock routing networks on an FPGA just to have an asynchronous reset. I know of no way around this and the solution is to actually just not use asynchronous resets at all. Just use synchronous resets.
The use of asynchronous resets appears to be a practice that was carried over from ASIC design early on that has been misapplied to FPGAs and repeatedly taught turning it into a bad habit. Asynchronous resets have advantages in ASIC design that do not carry over to FPGA design due to the hardware constraints of the FPGA. One such advantage is saving gates which you can do in an ASIC since you have control over everything, but in an FPGA the flip-flops are already there and all have a clock input anyways so you save nothing.
It is interesting that asynchronous resets in FPGAs also monitor the clock signal as well. You would think this would not be necessary since the reset is asynchronous, after all, so why would it ever need to trigger on a clock at all? The reason is because if the asynchronous reset deasserts too soon after a clock edge, there are metastability issues because timings are violated. A true asynchronous reset (as one that might appear in an ASIC which is where the practice came from) would not need to also trigger off the clock to stop this from happening.
The only weakness I have been able to find about synchronous resets is that if you have multiple clock domains and improperly use the synchronous reset with only the higher speed clocks in mind, it is possible for the slower clock domain to miss the reset pulse since the reset deasserts before the slow clock can tick to register the reset pulse. However, you can protect against this by design and I do not think it is a big deal compared to using a dedicated clock routing network for something so trivial as an asynchronous reset.
I posted the same on Xilinx Forum and I think it could be an issue with Vivado not properly cleaning the
After manually deleting it and re-generating the bitstream (which was fast because most of it was already compiled), the export gave me the proper