I've got a very simple circuit to update a register in my IP core.
input clk;
input rst;
input start;
input [31:0] ruleCount;
reg lastStart;
output reg [31:0] ruleCountReg;
always@(posedge clk)
if (rst)
lastStart <= 0;
else
lastStart <= start;
always@(posedge clk)
if (rst) begin
ruleCountReg <= 0;
end
else if (start && !lastStart) begin
ruleCountReg <= ruleCount;
end
The goal here is to register ruleCount
on the first cycle start
is asserted (some other trasitions depend on this as well). So, I register start
into lastStart
, wait for the condition, and then act appropriately.
I'm using Vivado 2015.4 and vSim XSim, and a Kintex Ultrascale 060. After elaborate/synthesis, I get the following circuit schematics:
My functional/RTL simulation matches what I'd expect. However, since the design wasn't functioning on the board, I opted to try a post-synthesis simulation, and got the following:
As shown,
start
gets raised by my testbench, and the output from the IBUF inserted by Vivado produces the same value. However, for reasons unknown, lastStart
fails to capture the value on either of the two clock edges when start
is high (t=35ns, t=45ns). Also, despite start&&!lastStart
being high, ruleCountReg
doesn't get updated either.
For comparison, here's the functional RTL simulation:
Is this a bug in Vivado? The Verilog is trivial, and it appears to be generating the correct schematics for the circuit, but could it be creating an incorrect netlist? Synthesis isn't producing any warnings that are relevant to these signals.
Edit: It appears as though xSim isn't updating any registers during the first 100ns of the simulation.
According to the Xilinx UG900 user guide, it's the intended behaviour.
In post-synthesis and post-implementation simulations, the GSR (Global Set/Reset) signal is automatically asserted for the first 100 ns to simulate the reset that occurs after configuration.
So it's dumb, but intentional.