---
# System prepended metadata

title: simulation issue study
tags: [transfer done, verilog]

---

# 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;

![](https://hackmd.io/_uploads/r1sJALguh.png)

## 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.

![](https://hackmd.io/_uploads/r1sJALguh.png)


## pass case : write by ioclk in negedge and read by coreclk in posedge

rx_sync_fifo 改變的時間提早半個 ioclck
![](https://hackmd.io/_uploads/rk2HTUe_2.png)


## 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)

![](https://hackmd.io/_uploads/S14MGQdOh.png)

```
//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

```