Commit 758be698 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

sim: trivial model of a 1000BaseX serdes

parent 70edaf0a
// Chuck Benz, Hollis, NH Copyright (c)2002
//
// The information and description contained herein is the
// property of Chuck Benz.
//
// Permission is granted for any reuse of this information
// and description as long as this copyright notice is
// preserved. Modifications may be made as long as this
// notice is preserved.
// per Widmer and Franaszek
task automatic f_8b10b_encode (input [8:0] datain, input dispin, output [9:0] dataout, output dispout) ;
logic ai = datain[0] ;
logic bi = datain[1] ;
logic ci = datain[2] ;
logic di = datain[3] ;
logic ei = datain[4] ;
logic fi = datain[5] ;
logic gi = datain[6] ;
logic hi = datain[7] ;
logic ki = datain[8] ;
logic aeqb = (ai & bi) | (!ai & !bi) ;
logic ceqd = (ci & di) | (!ci & !di) ;
logic l22 = (ai & bi & !ci & !di) |
(ci & di & !ai & !bi) |
( !aeqb & !ceqd) ;
logic l40 = ai & bi & ci & di ;
logic l04 = !ai & !bi & !ci & !di ;
logic l13 = ( !aeqb & !ci & !di) |
( !ceqd & !ai & !bi) ;
logic l31 = ( !aeqb & ci & di) |
( !ceqd & ai & bi) ;
// The 5B/6B encoding
logic ao = ai ;
logic bo = (bi & !l40) | l04 ;
logic co = l04 | ci | (ei & di & !ci & !bi & !ai) ;
logic doo = di & ! (ai & bi & ci) ;
logic eo = (ei | l13) & ! (ei & di & !ci & !bi & !ai) ;
logic io = (l22 & !ei) |
(ei & !di & !ci & !(ai&bi)) | // D16, D17, D18
(ei & l40) |
(ki & ei & di & ci & !bi & !ai) | // K.28
(ei & !di & ci & !bi & !ai) ;
// pds16 indicates cases where d-1 is assumed + to get our encoded value
logic pd1s6 = (ei & di & !ci & !bi & !ai) | (!ei & !l22 & !l31) ;
// nds16 indicates cases where d-1 is assumed - to get our encoded value
logic nd1s6 = ki | (ei & !l22 & !l13) | (!ei & !di & ci & bi & ai) ;
// ndos6 is pds16 cases where d-1 is + yields - disp out - all of them
logic ndos6 = pd1s6 ;
// pdos6 is nds16 cases where d-1 is - yields + disp out - all but one
logic pdos6 = ki | (ei & !l22 & !l13) ;
// some Dx.7 and all Kx.7 cases result in run length of 5 case unless
// an alternate coding is used (referred to as Dx.A7, normal is Dx.P7)
// specifically, D11, D13, D14, D17, D18, D19.
logic alt7 = fi & gi & hi & (ki |
(dispin ? (!ei & di & l31) : (ei & !di & l13))) ;
logic fo = fi & ! alt7 ;
logic go = gi | (!fi & !gi & !hi) ;
logic ho = hi ;
logic jo = (!hi & (gi ^ fi)) | alt7 ;
// nd1s4 is cases where d-1 is assumed - to get our encoded value
logic nd1s4 = fi & gi ;
// pd1s4 is cases where d-1 is assumed + to get our encoded value
logic pd1s4 = (!fi & !gi) | (ki & ((fi & !gi) | (!fi & gi))) ;
// ndos4 is pd1s4 cases where d-1 is + yields - disp out - just some
logic ndos4 = (!fi & !gi) ;
// pdos4 is nd1s4 cases where d-1 is - yields + disp out
logic pdos4 = fi & gi & hi ;
// only legal K codes are K28.0->.7, K23/27/29/30.7
// K28.0->7 is ei=di=ci=1,bi=ai=0
// K23 is 10111
// K27 is 11011
// K29 is 11101
// K30 is 11110 - so K23/27/29/30 are ei & l31
logic illegalk = ki &
(ai | bi | !ci | !di | !ei) & // not K28.0->7
(!fi | !gi | !hi | !ei | !l31) ; // not K23/27/29/30.7
// now determine whether to do the complementing
// complement if prev disp is - and pd1s6 is set, or + and nd1s6 is set
logic compls6 = (pd1s6 & !dispin) | (nd1s6 & dispin) ;
// disparity out of 5b6b is disp in with pdso6 and ndso6
// pds16 indicates cases where d-1 is assumed + to get our encoded value
// ndos6 is cases where d-1 is + yields - disp out
// nds16 indicates cases where d-1 is assumed - to get our encoded value
// pdos6 is cases where d-1 is - yields + disp out
// disp toggles in all ndis16 cases, and all but that 1 nds16 case
logic disp6 = dispin ^ (ndos6 | pdos6) ;
logic compls4 = (pd1s4 & !disp6) | (nd1s4 & disp6) ;
dispout = disp6 ^ (ndos4 | pdos4) ;
dataout = {(jo ^ compls4), (ho ^ compls4),
(go ^ compls4), (fo ^ compls4),
(io ^ compls6), (eo ^ compls6),
(doo ^ compls6), (co ^ compls6),
(bo ^ compls6), (ao ^ compls6)} ;
endtask
// Chuck Benz, Hollis, NH Copyright (c)2002
//
// The information and description contained herein is the
// property of Chuck Benz.
//
// Permission is granted for any reuse of this information
// and description as long as this copyright notice is
// preserved. Modifications may be made as long as this
// notice is preserved.
// per Widmer and Franaszek
task automatic f_8b10b_decode ( input [9:0] datain, input dispin, output [8:0] dataout, output dispout, output code_err, output disp_err) ;
logic ai = datain[0] ;
logic bi = datain[1] ;
logic ci = datain[2] ;
logic di = datain[3] ;
logic ei = datain[4] ;
logic ii = datain[5] ;
logic fi = datain[6] ;
logic gi = datain[7] ;
logic hi = datain[8] ;
logic ji = datain[9] ;
logic aeqb = (ai & bi) | (!ai & !bi) ;
logic ceqd = (ci & di) | (!ci & !di) ;
logic p22 = (ai & bi & !ci & !di) |
(ci & di & !ai & !bi) |
( !aeqb & !ceqd) ;
logic p13 = ( !aeqb & !ci & !di) |
( !ceqd & !ai & !bi) ;
logic p31 = ( !aeqb & ci & di) |
( !ceqd & ai & bi) ;
logic p40 = ai & bi & ci & di ;
logic p04 = !ai & !bi & !ci & !di ;
logic disp6a = p31 | (p22 & dispin) ; // pos disp if p22 and was pos, or p31.
logic disp6a2 = p31 & dispin ; // disp is ++ after 4 bits
logic disp6a0 = p13 & ! dispin ; // -- disp after 4 bits
logic disp6b = (((ei & ii & ! disp6a0) | (disp6a & (ei | ii)) | disp6a2 |
(ei & ii & di)) & (ei | ii | di)) ;
// The 5B/6B decoding special cases where ABCDE != abcde
logic p22bceeqi = p22 & bi & ci & (ei == ii) ;
logic p22bncneeqi = p22 & !bi & !ci & (ei == ii) ;
logic p13in = p13 & !ii ;
logic p31i = p31 & ii ;
logic p13dei = p13 & di & ei & ii ;
logic p22aceeqi = p22 & ai & ci & (ei == ii) ;
logic p22ancneeqi = p22 & !ai & !ci & (ei == ii) ;
logic p13en = p13 & !ei ;
logic anbnenin = !ai & !bi & !ei & !ii ;
logic abei = ai & bi & ei & ii ;
logic cdei = ci & di & ei & ii ;
logic cndnenin = !ci & !di & !ei & !ii ;
// non-zero disparity cases:
logic p22enin = p22 & !ei & !ii ;
logic p22ei = p22 & ei & ii ;
//logic p13in = p12 & !ii ;
//logic p31i = p31 & ii ;
logic p31dnenin = p31 & !di & !ei & !ii ;
//logic p13dei = p13 & di & ei & ii ;
logic p31e = p31 & ei ;
logic compa = p22bncneeqi | p31i | p13dei | p22ancneeqi |
p13en | abei | cndnenin ;
logic compb = p22bceeqi | p31i | p13dei | p22aceeqi |
p13en | abei | cndnenin ;
logic compc = p22bceeqi | p31i | p13dei | p22ancneeqi |
p13en | anbnenin | cndnenin ;
logic compd = p22bncneeqi | p31i | p13dei | p22aceeqi |
p13en | abei | cndnenin ;
logic compe = p22bncneeqi | p13in | p13dei | p22ancneeqi |
p13en | anbnenin | cndnenin ;
logic ao = ai ^ compa ;
logic bo = bi ^ compb ;
logic co = ci ^ compc ;
logic doo = di ^ compd ;
logic eo = ei ^ compe ;
logic feqg = (fi & gi) | (!fi & !gi) ;
logic heqj = (hi & ji) | (!hi & !ji) ;
logic fghj22 = (fi & gi & !hi & !ji) |
(!fi & !gi & hi & ji) |
( !feqg & !heqj) ;
logic fghjp13 = ( !feqg & !hi & !ji) |
( !heqj & !fi & !gi) ;
logic fghjp31 = ( (!feqg) & hi & ji) |
( !heqj & fi & gi) ;
logic dispout = (fghjp31 | (disp6b & fghj22) | (hi & ji)) & (hi | ji) ;
logic ko = ( (ci & di & ei & ii) | ( !ci & !di & !ei & !ii) |
(p13 & !ei & ii & gi & hi & ji) |
(p31 & ei & !ii & !gi & !hi & !ji)) ;
logic alt7 = (fi & !gi & !hi & // 1000 cases, where disp6b is 1
((dispin & ci & di & !ei & !ii) | ko |
(dispin & !ci & di & !ei & !ii))) |
(!fi & gi & hi & // 0111 cases, where disp6b is 0
(( !dispin & !ci & !di & ei & ii) | ko |
( !dispin & ci & !di & ei & ii))) ;
logic k28 = (ci & di & ei & ii) | ! (ci | di | ei | ii) ;
// k28 with positive disp into fghi - .1, .2, .5, and .6 special cases
logic k28p = ! (ci | di | ei | ii) ;
logic fo = (ji & !fi & (hi | !gi | k28p)) |
(fi & !ji & (!hi | gi | !k28p)) |
(k28p & gi & hi) |
(!k28p & !gi & !hi) ;
logic go = (ji & !fi & (hi | !gi | !k28p)) |
(fi & !ji & (!hi | gi |k28p)) |
(!k28p & gi & hi) |
(k28p & !gi & !hi) ;
logic ho = ((ji ^ hi) & ! ((!fi & gi & !hi & ji & !k28p) | (!fi & gi & hi & !ji & k28p) |
(fi & !gi & !hi & ji & !k28p) | (fi & !gi & hi & !ji & k28p))) |
(!fi & gi & hi & ji) | (fi & !gi & !hi & !ji) ;
logic disp6p = (p31 & (ei | ii)) | (p22 & ei & ii) ;
logic disp6n = (p13 & ! (ei & ii)) | (p22 & !ei & !ii) ;
logic disp4p = fghjp31 ;
logic disp4n = fghjp13 ;
code_err = p40 | p04 | (fi & gi & hi & ji) | (!fi & !gi & !hi & !ji) |
(p13 & !ei & !ii) | (p31 & ei & ii) |
(ei & ii & fi & gi & hi) | (!ei & !ii & !fi & !gi & !hi) |
(ei & !ii & gi & hi & ji) | (!ei & ii & !gi & !hi & !ji) |
(!p31 & ei & !ii & !gi & !hi & !ji) |
(!p13 & !ei & ii & gi & hi & ji) |
(((ei & ii & !gi & !hi & !ji) |
(!ei & !ii & gi & hi & ji)) &
! ((ci & di & ei) | (!ci & !di & !ei))) |
(disp6p & disp4p) | (disp6n & disp4n) |
(ai & bi & ci & !ei & !ii & ((!fi & !gi) | fghjp13)) |
(!ai & !bi & !ci & ei & ii & ((fi & gi) | fghjp31)) |
(fi & gi & !hi & !ji & disp6p) |
(!fi & !gi & hi & ji & disp6n) |
(ci & di & ei & ii & !fi & !gi & !hi) |
(!ci & !di & !ei & !ii & fi & gi & hi) ;
dataout = {ko, ho, go, fo, eo, doo, co, bo, ao} ;
// my disp err fires for any legal codes that violate disparity, may fire for illegal codes
disp_err = ((dispin & disp6p) | (disp6n & !dispin) |
(dispin & !disp6n & fi & gi) |
(dispin & ai & bi & ci) |
(dispin & !disp6n & disp4p) |
(!dispin & !disp6p & !fi & !gi) |
(!dispin & !ai & !bi & !ci) |
(!dispin & !disp6p & disp4n) |
(disp6p & disp4p) | (disp6n & disp4n)) ;
endtask // f_8b10b_decode
`timescale 10fs/10fs
`include "simdrv_defs.svh"
`include "8b10b_encoder.svh"
`timescale 10fs/10fs
module wr_1000basex_phy_tx_path_model
(
input clk_ref_i,
input rst_n_i,
input [15:0] tx_data_i,
input [1:0] tx_k_i,
output tx_disparity_o,
output reg tx_o,
output reg rdy_o
);
time t_prev, t_cur, t_delta, t_delta_prev;
int stab_cnt;
reg pll_en = 0;
int pll_stab_count = 0;
const int c_pll_lock_thr = 100;
reg clk_tx = 0;
always@(posedge clk_ref_i)
if(pll_en)
begin
automatic int i;
for(i=0;i<20; i++)
begin
clk_tx <= 1;
#(t_delta / 40);
clk_tx <= 0;
#(t_delta / 40);
end
end
always@(posedge clk_ref_i or negedge rst_n_i)
if (!rst_n_i)
begin
pll_stab_count <= 0;
pll_en <= 0;
end else begin
t_prev = t_cur;
t_cur = $time;
t_delta = t_cur - t_prev;
t_delta_prev = t_delta;
if(t_delta_prev == t_delta && t_delta > 1ns)
begin
if( pll_stab_count < c_pll_lock_thr)
pll_stab_count <= pll_stab_count + 1;
else
pll_en <= 1;
end else begin
pll_stab_count <= 0;
pll_en <= 0;
end
end // else: !if(!rst_n_i)
assign rdy_o = pll_en;
reg [19:0] tx_d;
reg [19:0] tx_sreg;
int tx_bit_count = 0;
reg clk_ref_d = 0;
always@(posedge clk_tx)
begin
clk_ref_d <= clk_ref_i;
if(!clk_ref_d && clk_ref_i)
begin
tx_sreg <= tx_d;
tx_bit_count <= 1;
tx_o <= tx_d[0];
end else begin
tx_bit_count <= tx_bit_count + 1;
tx_o <= tx_sreg[tx_bit_count];
end
end
wire [19:0] encoded;
reg cur_disp = 0;
reg tmp_disp;
always@(posedge clk_tx)
begin
f_8b10b_encode ( {tx_k_i[0], tx_data_i[7:0] }, cur_disp, tx_d[19:10], tmp_disp );
f_8b10b_encode ( {tx_k_i[1], tx_data_i[15:8] }, tmp_disp, tx_d[9:0], cur_disp );
end
assign tx_disparity_o = cur_disp;
endmodule // phy_tx_path_model
module wr_1000basex_phy_rx_path_model
(
input clk_ref_i,
input rst_n_i,
output reg [15:0] rx_data_o,
output reg [1:0] rx_k_o,
output reg rx_error_o,
output reg [4:0] rx_bitslide_o,
output rx_rbclk_o,
input rx_i,
output rdy_o
);
reg clk_rx_ser = 0;
parameter time g_bit_time = 800ps;
parameter time g_bit_time_tollerance = 0.05ns;
parameter time g_pll_resolution = 10ps;
time t_prev, t_cur, t_delta, t_delta_prev, t_bit_time;
int bit_time_valid_cnt = 0;
reg bit_time_ok = 0;
always@(posedge rx_i or negedge rx_i)
if (!rst_n_i)
begin
bit_time_valid_cnt <= 0;
bit_time_ok <= 0;
end else begin
t_prev = t_cur;
t_cur = $time;
t_delta = t_cur - t_prev;
if(t_delta > g_bit_time - g_bit_time_tollerance && t_delta < g_bit_time + g_bit_time_tollerance )
begin
t_bit_time = t_delta;
//$display("BitTime: %t %d", t_bit_time, bit_time_ok);
if(bit_time_valid_cnt == 1000)
bit_time_ok <= 1;
else
bit_time_valid_cnt++;
end
end // else: !if(!rst_n_i)
assign rdy_o = 1;
reg rx_d = 0;
always #(g_pll_resolution)
rx_d <= rx_i;
always begin
if(bit_time_ok)
begin
if(rx_d != rx_i)
begin
clk_rx_ser <= 0;
#1;
end
#(t_bit_time/2);
clk_rx_ser <= 1;
#(t_bit_time/2);
clk_rx_ser <= 0;
end else // if (bit_time_ok)
#(g_pll_resolution);
end // always
reg [19:0] rx_sreg;
reg clk_rx_par = 0;
int clk_par_div_cnt = 0;
always@(posedge clk_rx_ser)
begin
rx_sreg <= {rx_sreg[18:0], rx_i};
// $display("rxsreg %b", rx_sreg);
if(rx_sreg[19:10] == 10'b0011111010 || rx_sreg[19:10] == ~10'b0011111010)
begin
// $display("Comma!");
clk_par_div_cnt <= 2;
end else if(clk_par_div_cnt == 19)
clk_par_div_cnt <= 0;
else
clk_par_div_cnt <= clk_par_div_cnt + 1;
end // always@ (posedge clk_rx_ser)
always@(posedge clk_rx_ser)
clk_rx_par <= (clk_par_div_cnt < 10 ? 1'b1 : 1'b0);
reg cur_disp = 0;
function bit[9:0] f_reverse(bit[9:0] d);
return {d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9]};
endfunction // f_reverse
always@(posedge clk_rx_par)
if(!rst_n_i)
begin
cur_disp <= 0;
end else begin
automatic logic tmp_disp, code_err, disp_err;
automatic logic [8:0] rx_out1, rx_out2;
f_8b10b_decode( f_reverse(rx_sreg[19:10]), cur_disp, rx_out1, tmp_disp, code_err, disp_err);
f_8b10b_decode( f_reverse(rx_sreg[9:0]), tmp_disp, rx_out2, cur_disp, code_err, disp_err);
rx_k_o <= {rx_out1[8], rx_out2[8]};
rx_data_o <= {rx_out1[7:0], rx_out2[7:0]};
rx_error_o <= 0;
rx_bitslide_o <= 0;
end // else: !if(!rst_n_i)
assign rx_rbclk_o = clk_rx_par;
endmodule
module wr_1000basex_phy_model
(
// Reference 62.5 MHz clock input for the TX/RX logic (not the GTX itself)
input clk_ref_i,
input [15:0] tx_data_i,
input [1:0] tx_k_i,
output tx_disparity_o,
output tx_enc_err_o,
output rx_rbclk_o,
output [15:0] rx_data_o,
output [1:0] rx_k_o,
output rx_enc_err_o,
output [4:0] rx_bitslide_o,
input rst_i,
input loopen_i,
output pad_txn_o,
output pad_txp_o,
input pad_rxn_i,
input pad_rxp_i,
output rdy_o
);
wire ser_tx, ser_rx, ready_tx, ready_rx;
assign rdy_o = ready_tx & ready_rx;
wr_1000basex_phy_tx_path_model U_TX
(
.clk_ref_i(clk_ref_i),
.rst_n_i(~rst_i),
.tx_data_i(tx_data_i),
.tx_k_i(tx_k_i),
.tx_disparity_o(tx_disparity_o),
.tx_o(ser_tx),
.rdy_o(ready_tx)
);
wr_1000basex_phy_rx_path_model U_RX
(
.clk_ref_i(clk_ref_i),
.rst_n_i(~rst_i),
.rx_data_o(rx_data_o),
.rx_k_o(rx_k_o),
.rx_error_o(rx_enc_err_o),
.rx_bitslide_o(rx_bitslide_o),
.rx_rbclk_o(rx_rbclk_o),
.rx_i(ser_rx),
.rdy_o(ready_rx)
);
assign ser_rx = loopen_i ? ser_tx : pad_rxp_i;
assign pad_txp_o = loopen_i ? 1'bz : ser_tx;
assign pad_txn_o = loopen_i ? 1'bz : ~ser_tx;
endmodule // wr_1000basex_phy_model
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment