# simulation issue : data get early 1T
###### tags: `verilog`
## issue desciption
- this issue is cause by simulation behavior.
- the coreclk is come from ioclk and the clock ratio is 1:4
## root cause
the ioclk is early then coreclk.
simulation 將ioclk和coreclk分為兩個不同的時間點,依時間順序做計算
Step1. simulation 計算rx_sync_fifo的結果 @ posedge of ioclk
rx_sync_fifo <= rx_shift_reg;
Step2. simulation 使用 rx_sync_fifo result in step 1. and update to rxdata @ posedge of coreclk
rxdata <= rx_sync_fifo;

## code with issue
```
//write by ioclk in negedge and read by coreclk in posedge then simulation result is ok.
reg [CLK_RATIO-1:0] rx_sync_fifo;
reg rx_sync_fifo_valid;
// always @(negedge ioclk or posedge rst) begin //use negedge, simulation result is ok.
always @(posedge ioclk or posedge rst) begin //use posedge, the simulation result is early 1T in rxdata
if (rst ) begin
rx_sync_fifo <= 0;
rx_sync_fifo_valid <= 0;
end
else begin
if (rx_start && rx_shift_reg_valid) begin
rx_sync_fifo <= rx_shift_reg;
rx_sync_fifo_valid <= 1;
end
else begin
rx_sync_fifo <= rx_sync_fifo;
rx_sync_fifo_valid <= rx_sync_fifo_valid;
end
end
end
reg [CLK_RATIO-1:0] rxdata;
reg rxdata_valid;
assign rxdata_out = rxdata;
assign rxdata_out_valid = rxdata_valid;
always @(posedge coreclk or posedge rst) begin
if (rst ) begin
rxdata <= 0;
rxdata_valid <= 0;
end
else begin
rxdata <= rx_sync_fifo;
rxdata_valid <= rx_sync_fifo_valid;
end
end
```
## fail case : write by ioclk in posedge and read by coreclk in posedge
in simulation rx_sync_fifo 值改變後,馬上被 rxdata sample 到,但是這個 code 去做 synthesis 應該是正常的,也就是說出現了 simulation and synthesis result mismatch.

## pass case : write by ioclk in negedge and read by coreclk in posedge
rx_sync_fifo 改變的時間提早半個 ioclck

## solution 1 (不建議):
- this solution imapct timing in rx_shift_reg, 1/2 T margin
- write by ioclk posedge
- read by ioclk negedge
reference the code :
write by ioclk in negedge and read by coreclk in posedge then simulation result is ok.
```
reg clk_div4;
assign out = clk_div4;
reg clk_div2;
//for use non-block assigmnet
always @(posedge in or negedge resetb)
if ( !resetb ) clk_div2 <= 0;
else clk_div2 <= ~clk_div2;
always @(posedge clk_div2 or negedge resetb)
if ( !resetb ) clk_div4 <= 0;
else clk_div4 <= ~clk_div4;
```
```
always @(negedge ioclk or posedge rst) begin //use negedge, simulation result is ok.
//always @(posedge ioclk or posedge rst) begin //use posedge, the simulation result is early 1T in rxdata
if (rst ) begin
rx_sync_fifo <= 0;
rx_sync_fifo_valid <= 0;
end
else begin
if (rx_start && rx_shift_reg_valid) begin
rx_sync_fifo <= rx_shift_reg;
rx_sync_fifo_valid <= 1;
end
else begin
rx_sync_fifo <= rx_sync_fifo;
rx_sync_fifo_valid <= rx_sync_fifo_valid;
end
end
end
```
## solution 2 (better solution):
reference [Gotcha 29: Sequential logic that requires blocking assignments](https://hackmd.io/@TonyHo/rJwPNuIu3)

```
//for use block assigmnet to avoid race condition in simulation
always @(posedge in or negedge resetb)
if ( !resetb ) clk_div2 = 0;
else clk_div2 = ~clk_div2;
always @(posedge clk_div2 or negedge resetb)
if ( !resetb ) clk_div4 = 0;
else clk_div4 = ~clk_div4;
```
```
always @(posedge ioclk or posedge rst) begin
if (rst ) begin
rx_sync_fifo <= 0;
rx_sync_fifo_valid <= 0;
end
else begin
if (rx_start && rx_shift_reg_valid) begin
rx_sync_fifo <= rx_shift_reg;
rx_sync_fifo_valid <= 1;
end
else begin
rx_sync_fifo <= rx_sync_fifo;
rx_sync_fifo_valid <= rx_sync_fifo_valid;
end
end
end
```