# io_serdes.v
## Config register
### Config register write
```
// if both axi_awvalid_in=1 and axi_wvalid_in=1 then output axi_awready_out = 1 and axi_wready_out = 1
assign axi_awready_out = (axi_awvalid_in && axi_wvalid_in) ? 1 : 0;
assign axi_wready_out = (axi_awvalid_in && axi_wvalid_in) ? 1 : 0;
//write register
always @(posedge axi_clk or negedge axi_reset_n) begin
if ( !axi_reset_n ) begin
rxen_ctl <= 0;
txen_ctl <= 0;
end
else begin
if ( axi_awvalid_in && axi_wvalid_in ) begin //when axi_awvalid_in=1 and axi_wvalid_in=1 means axi_awready_out=1 and axi_wready_out=1
if (axi_awaddr == 10'h000 && (axi_wstrb[0] == 1) ) begin //offset 0
rxen_ctl <= axi_wdata[0];
txen_ctl <= axi_wdata[1];
end
else begin
rxen_ctl <= rxen_ctl;
txen_ctl <= txen_ctl;
end
end
end
end
```
### Config register read
```
// io serdes always output axi_arready = 1 and don't care the axi_arvalid & axi_araddr
// io serdes only support 2 register bits in offset 0. config read other address offset is reserved.
assign axi_arready = 1;
// io serdes always output axi_rvalid = 1 and axi_rdata = { 30'b0, txen_ctl, rxen_ctl }
assign axi_rvalid = 1;
assign axi_rdata = { 30'b0, txen_ctl, rxen_ctl };
```
### config read/write waveform

## txclk
```
assign txclk = ioclk&txen; //use negedge to avoid glitch in txclk.
```
## txen
- txen use negedge to avoid glitch in txclk
```
reg txen;
always @(negedge ioclk or negedge axis_rst_n) begin
if ( !axis_rst_n ) begin
txen <= 0;
end
else begin
if ( (txen_ctl || rx_received_data) && phase_cnt == 3 ) // set txen=1 when timeout or rx_received_data==1
// if rx_received_data==1 before timeout, it means remote side txen is ealry then local side.
// then we should set local site txen=1 to allow local site provide ready signal to remote side in tx path.
// It is to avoid local site rx fifo full in axis switch.
txen <= 1;
else
txen <= txen;
end
end
```
### txclk waveform

### txen_ctl before rx_received_data

### txen_ctl after rx_received_data

## TX Path - AS to IS
```
always @(posedge coreclk or negedge axis_rst_n) begin
if ( !axis_rst_n || ~txen) begin
as_is_tdata_buf <= 0;
as_is_tstrb_buf <= 0;
as_is_tkeep_buf <= 0;
as_is_tid_tuser_buf <= 0;
as_is_tlast_tvalid_tready_buf <= 0;
end
else begin
if (is_as_tready && as_is_tvalid) begin //data transfer from Axis siwtch to io serdes when is_as_tready=1 and as_is_tvalid=1
as_is_tdata_buf <= as_is_tdata;
as_is_tstrb_buf <= as_is_tstrb;
as_is_tkeep_buf <= as_is_tkeep;
as_is_tid_tuser_buf[3:2] <= as_is_tid;
as_is_tid_tuser_buf[1:0] <= as_is_tuser;
as_is_tlast_tvalid_tready_buf[2] <= as_is_tlast;
as_is_tlast_tvalid_tready_buf[1] <= as_is_tvalid;
as_is_tlast_tvalid_tready_buf[0] <= as_is_tready;
end
else begin
as_is_tdata_buf <= as_is_tdata;
as_is_tstrb_buf <= as_is_tstrb;
as_is_tkeep_buf <= as_is_tkeep;
as_is_tid_tuser_buf[3:2] <= as_is_tid;
as_is_tid_tuser_buf[1:0] <= as_is_tuser;
as_is_tlast_tvalid_tready_buf[2] <= as_is_tlast;
as_is_tlast_tvalid_tready_buf[1] <= 0; // set as_is_tvalid =0 to remote side
as_is_tlast_tvalid_tready_buf[0] <= as_is_tready;
end
end
end
```
### TX Path Wavefrom
- first data transfer in bule line.

## is_as_tready_out
- avoid dead lock issue
- // when txen==1 and still not recevies data from remote side then set is_as_tready_out=1 to avoid dead lock issue.
```
reg is_as_tready_out;
assign is_as_tready = is_as_tready_out;
always @(posedge coreclk or negedge axis_rst_n) begin
if ( !axis_rst_n || !txen ) begin
is_as_tready_out <= 0; //set is_as_tready_out=0 when txen == 0
end
else begin
if (rx_received_data == 0) is_as_tready_out <= 1; // when txen==1 and still not recevies data from remote side then set is_as_tready_out=1 to avoid dead lock issue.
else is_as_tready_out <= is_as_tready_remote; // when txen == 1 and rx_received_data==1 (received data from remote side) then is_as_tready_out come from is_as_tready_remote (remote side)
end
end
```

## Serial_Data_Out_tdata
```
genvar j;
generate
for (j=0; j<8; j=j+1 ) begin
assign Serial_Data_Out_tdata[j] = as_is_tdata_buf[j*4+tx_shift_phase_cnt] & txen ;
end
endgenerate
```

## RX Path - IS to AS
### rxen
```
always @(negedge ioclk or negedge axis_rst_n) begin
if ( !axis_rst_n ) begin
rxen <= 0;
end
else begin
if (rxen_ctl)
rxen <= 1;
else
rxen <= rxen;
end
end
```
### fsic_io_serdes_rx
```
genvar i;
generate
for (i=0; i<8; i=i+1 ) begin
fsic_io_serdes_rx #(
.pRxFIFO_DEPTH(pRxFIFO_DEPTH),
.pCLK_RATIO(pCLK_RATIO)
)
fsic_io_serdes_rx_tdata(
.axis_rst_n(axis_rst_n),
.rxclk(rxclk),
.rxen(rxen),
.ioclk(ioclk),
.coreclk(coreclk),
.Serial_Data_in(Serial_Data_In_tdata[i]),
.rxdata_out(is_as_tdata[i*4+3:i*4])
// .rxdata_out_valid(rxdata_out_valid)
);
end
endgenerate
fsic_io_serdes_rx #(
.pRxFIFO_DEPTH(pRxFIFO_DEPTH),
.pCLK_RATIO(pCLK_RATIO)
)
fsic_io_serdes_rx_tstrb(
.axis_rst_n(axis_rst_n),
.rxclk(rxclk),
.rxen(rxen),
.ioclk(ioclk),
.coreclk(coreclk),
.Serial_Data_in(Serial_Data_In_tstrb),
.rxdata_out(is_as_tstrb)
// .rxdata_out_valid(rxdata_out_valid)
);
fsic_io_serdes_rx #(
.pRxFIFO_DEPTH(pRxFIFO_DEPTH),
.pCLK_RATIO(pCLK_RATIO)
)
fsic_io_serdes_rx_tkeep(
.axis_rst_n(axis_rst_n),
.rxclk(rxclk),
.rxen(rxen),
.ioclk(ioclk),
.coreclk(coreclk),
.Serial_Data_in(Serial_Data_In_tkeep),
.rxdata_out(is_as_tkeep)
// .rxdata_out_valid(rxdata_out_valid)
);
fsic_io_serdes_rx #(
.pRxFIFO_DEPTH(pRxFIFO_DEPTH),
.pCLK_RATIO(pCLK_RATIO)
)
fsic_io_serdes_rx_tid_tuser(
.axis_rst_n(axis_rst_n),
.rxclk(rxclk),
.rxen(rxen),
.ioclk(ioclk),
.coreclk(coreclk),
.Serial_Data_in(Serial_Data_In_tid_tuser),
.rxdata_out( {is_as_tid[1:0], is_as_tuser[1:0]})
// .rxdata_out_valid(rxdata_out_valid)
);
wire rx_received_data;
fsic_io_serdes_rx #(
.pRxFIFO_DEPTH(pRxFIFO_DEPTH),
.pCLK_RATIO(pCLK_RATIO)
)
fsic_io_serdes_rx_fc(
.axis_rst_n(axis_rst_n),
.rxclk(rxclk),
.rxen(rxen),
.ioclk(ioclk),
.coreclk(coreclk),
.Serial_Data_in(Serial_Data_In_tlast_tvalid_tready),
.rxdata_out( {is_as_tlast, is_as_tvalid, is_as_tready_remote}), // only connect [2:0]
.rxdata_out_valid(rx_received_data)
);
```
- rx_received_data from rxdata_out_valid
## force FPGA de-assert as_is_tready to simulate defect Rx buffer <=7 (new code in https://github.com/bol-edu/fsic_fpga/commit/a87d4c9781aa4916eafa6cf12c511e7ada2ffb63)
- Step 1. force FPGA de-assert as_is_tready to simulate defect Rx buffer <=7
- Step 2. SOC detect is_as_tready = 0
- Step 3. SOC output as_is_tlast_tvalid_tready_buf[1] = 0
- Step 4. FPGA still received 8 clocks of data after Step 1
