I have a part of Verilog code that is basically trying to synthesize a flip-flop. I have been experimenting and it seems that I can come up with two ways of writing it.
The first way being :
always @(posedge(clk),posedge(reset)) begin
if(reset) begin
g <= 1'b0;
end else begin
if((~wr_full) && (~fifo_empty)) begin
g <= ~ g;
end else begin
g <= g;
end
end
end
And the second way being :
reg g_next;
always @(posedge(clk),posedge(reset)) begin
if(reset) begin
g <= 1'b0;
end else begin
g <= g_next;
end
end
always @* begin
if((~wr_full) && (~fifo_empty)) begin
g_next = ~ g;
end else begin
g_next = g;
end
end
It turns out that both these codes synthesize to become the exact same circuit (which was expected) :
But their behaviour in simulation is different. In the first case, as soon as the condition in the if statement (~tx_busy) && (~output_fifo_empty)
becomes true
, the output of the flip flop changes, but in the second case, the change in output occurs one clock cycle after the condition becomes true
.
So, my questions are :
1) Why are the behavioural simulation results different, even though both the codes synthesize to become the same circuit.
2) Which one of the behaviours is expected as the output of the synthesized circuit, and why? After looking at the synthesized circuit, it seems logical to infer that the behaviour will be that of the second circuit, but why is that (the behaviour I wanted to infer was the first one). And if this is the case, how do I enforce the first behaviour (maybe a latch ?)
3) I have been using these two methods interchangeably to produce the behaviours I wanted, but I have now realized that these two synthesize to be the same circuit. How does this affect my other circuits (do I not understand how they work, but they still work as expected ?)
4) How do I know that the circuit behaviour that I inferred in behavioural simulation will be the one of the synthesized circuit (this experience basically questions all the beliefs I had about the behaviours of simulated and synthesized designs)
EDIT : since the codes are very long, i'd rather not post them here. I have uploaded them here.
There are three floders.
The
traffic_generator
folder contains the filetraffic_generator.v
and the testbench for the sametraffic_generator_tb.v
. These are the top level codes.The
pulse_generator
folder contains the include filepulse_generator.v
. I am aware that this code is not yet synthesizable, but I can get a synthesizable code with the same behaviour (Right?).The
my_fifo
folder contains yet another include filemy_fifo.v
. I suspect there might be some problem due to the way the empty flag is updated, but I can't seem to figure it out.
clk
,tx_busy
, andoutput_fifo_empty
. I have a feelingtx_busy
andoutput_fifo_empty
are assigned with blocking assignments and changing at the same timestep asclk
\$\endgroup\$output_fifo_empty
, it is assigned with blocking assignment. As of now,tx_busy
is kept low (for simulation purposes). But when connected to the uart, tx_busy will also be assigned with a blocking assignment. \$\endgroup\$tx_busy
withwr_full
,output_fifo_empty
withfifo_empty
, andgenerate_output_fifo_pop_pulse
withg
. Also, in this configuration, I don't know whetherwr_full
is generated by a blocking or non-blocking assignment (since it is a signal generated by the memory controller). How does this change things ? \$\endgroup\$@(posedge clk)
instead of#
delays to gate transitions that should be in sync with the clock. \$\endgroup\$