在课程高速通信中的信道编码–加扰与解扰 中,我们学习了乘性加扰的算法,但不是一个完整的通讯工程。之前我们学习过使用400M时钟对100M的通讯数据采样,学习过400M下的得到的数据如何同步到100M时钟域下。利用我们之前学习过的知识,增加乘性加扰,解扰算法,就可以实现整个通讯工程了。
仿真文件:
`timescale 1 ns / 1 ps
module tb
(
);
parameter SYNC1 = 8'b1010_1010;
parameter SYNC2 = 8'b1010_1011;
parameter PERIOD = 20 ; //周期20
reg pll_rst; //实体模块PLL的rst信号
wire tx_rx; // 收发在testbench的回环信号
wire clk_100M;
wire pll_locked; //实体PLL锁定信号
wire rst = !pll_locked; //Testbench内生成复位信号
reg [ 7: 0 ] tx_data; //待发送数据
wire rx_vld;
wire rx_rdy;
wire [ 7: 0 ] rx_data;
reg inclk ; // 模拟板级提供的输入时钟
reg [ 2: 0 ] tx_st;
initial
begin
inclk = 1'b0;
#( PERIOD / 2 );
forever
#( PERIOD / 2 ) inclk = ~inclk;
end
//always #10 inclk=~inclk;
initial
begin
pll_rst = 1'b1;
tx_data = 0;
#50 pll_rst = 1'b0;
end
wire tx_rdy;
reg tx_vld = 0;
reg tx_en = 0;
reg [5:0] send_cnt = 0;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
tx_en <= 0;
tx_st <= 0;
tx_data <= 0;
end
else
begin
case ( tx_st )
0:
begin
tx_en <= 0;
send_cnt <= 0;
tx_data <= 0;
tx_vld <= 0;
tx_st <= 1;
end
1:
begin
tx_vld <= 1;
tx_st <= 2;
end
2:
begin
if(tx_rdy)
begin
tx_data <= 0;
tx_en <= 1;
send_cnt <= send_cnt + 1;
// if(send_cnt == 7)
tx_st <= 3;
end
end
3:
begin
tx_en <= 0;
if(tx_rdy)
begin
tx_en <= 1;
tx_data <= tx_data + 1;
send_cnt <= send_cnt + 1;
// if ( send_cnt == 23 )
if ( send_cnt == 31 )
begin
send_cnt <= 0;
tx_st <= 7;
end
end
end
6:
begin
if(tx_rdy)
begin
tx_data <= 8'hff;
send_cnt <= send_cnt + 1;
if(send_cnt == 31)
begin
send_cnt <= 0;
tx_st <= 7;
end
end
end
7:
begin
tx_en <= 0;
tx_vld <= 0;
send_cnt <= send_cnt + 1;
if(&send_cnt)
begin
tx_st <= 0;
end
end
default:
tx_st <= 0;
endcase
end
hs_txrx hs_txrx_inst
(
.inclk ( inclk ),
.pll_rst ( pll_rst ),
.tx_data ( tx_data ),
.tx_en ( tx_en ),
.tx_rdy ( tx_rdy ),
.tx_vld ( tx_vld ),
.tx ( tx_rx ),
.rx ( tx_rx ),
.rx_vld ( rx_vld ),
.rx_rdy ( rx_rdy ),
.rx_data ( rx_data ),
.clk_100M ( clk_100M ),
.pll_locked ( pll_locked )
);
endmodule
testbench 文件和加性加扰中使用的tb 文件相同。
顶层文件:
module hs_txrx
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
// parameter SCRAMB_SYNC = 23'b0,
parameter SYNC1 = 8'b1010_1010,
parameter SYNC2 = 8'b1010_1011
)
(
input inclk,
input pll_rst,
input [ 7: 0 ] tx_data,
input tx_en,
output tx_rdy,
input tx_vld,
output tx,
input rx,
output rx_rdy,
output rx_vld,
output [ 7: 0 ] rx_data,
output clk_100M,
output pll_locked
);
wire clk_400M;
wire rst = !pll_locked;
tx_pcs
#(
.SCRAMB_SYNC( SCRAMB_SYNC ),
.SYNC1 ( SYNC1 ),
.SYNC2 ( SYNC2 )
)
tx_pcs_inst
(
.rst ( rst ),
.clk_100M ( clk_100M ),
.tx_data ( tx_data ), // 100M的时钟对应的数据
.tx_en ( tx_en ),
.tx_vld ( tx_vld ),
.tx_rdy ( tx_rdy ),
.tx_out ( tx )
);
rev_pcs
#(
.SCRAMB_SYNC( SCRAMB_SYNC ),
.SYNC1 ( SYNC1 ),
.SYNC2 ( SYNC2 )
)
recv_pcs_inst
(
.rst ( rst ),
.clk_100M ( clk_100M ),
.clk_400M ( clk_400M ),
.rx_vld ( rx_vld ),
.rx_data ( rx_data ),
.rx_rdy ( rx_rdy ),
.rx ( rx )
);
pll1 pll1_inst
(
.areset ( pll_rst ), //1'b0;
.inclk0 ( inclk ),
.c0 ( clk_10M ),
.c1 ( clk_100M ),
.c2 ( clk_400M ),
.locked ( pll_locked )
);
endmodule
tx_pcs.v
module tx_pcs
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
parameter SYNC1 = 8'b1010_1010,
parameter SYNC2 = 8'b1010_1011
)
(
input clk_100M,
input tx_vld,
input [ 7: 0 ] tx_data, // 100M的时钟对应的数据
input tx_en,
output reg tx_rdy = 0,
output tx_out,
input rst
);
reg tx_en_r;
reg tx_en_ack;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
tx_en_r <= 0;
end
else
begin
if ( tx_en )
begin
tx_en_r <= 1'b1;
end
else if ( tx_en_ack )
tx_en_r <= 0;
end
reg [ 7: 0 ] tx_data_r;
reg [ 7: 0 ] tx_sht;
reg [ 2: 0 ] tx_sht_count;
reg [ 1: 0 ] tx_st;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
tx_data_r <= SYNC1;
tx_sht <= SYNC1;
tx_sht_count <= 0;
tx_rdy <= 1'b0;
tx_en_ack <= 1'b0;
tx_st <= 0;
end
else
begin
case ( tx_st )
0:
begin
tx_data_r <= SYNC1;
tx_sht <= tx_data_r;
tx_sht_count <= 0;
tx_rdy <= 1'b0;
tx_en_ack <= 1'b0;
tx_st <= 1;
end
1:
begin
tx_rdy <= 1'b0;
if ( tx_sht_count == 7 )
begin
tx_sht <= tx_data_r;
tx_sht_count <= 0;
if ( tx_vld )
begin
tx_data_r <= SYNC2;
tx_en_ack <= 1'b1;
tx_rdy <= 1'b1;
tx_st <= 2;
end
end
else
begin
tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
tx_sht_count <= tx_sht_count + 1'b1;
end
end
2:
begin
tx_en_ack <= 1'b0;
tx_rdy <= 1'b0;
if ( tx_sht_count == 7 )
begin
tx_sht <= tx_data_r;
tx_sht_count <= 0;
if ( tx_en_r )
begin
tx_en_ack <= 1'b1;
tx_data_r <= tx_data;
tx_rdy <= 1'b1;
end
else if ( !tx_vld )
begin
tx_en_ack <= 1'b1;
tx_data_r <= SYNC1;
tx_st <= 3;
end
end
else
begin
tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
tx_sht_count <= tx_sht_count + 1'b1;
end
end
3:
begin
tx_en_ack <= 1'b0;
tx_rdy <= 1'b0;
if ( tx_sht_count == 6 )
tx_st <= 0;
tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
tx_sht_count <= tx_sht_count + 1'b1;
end
default: tx_st <= 0;
endcase
end
wire tx_bit = tx_sht[ 0 ];
trans_pma # (.SCRAMB_SYNC ( SCRAMB_SYNC ) )
trans_pma_inst
(
.clk_100M ( clk_100M ),
.tx_in ( tx_bit ),
.tx_out ( tx_out ),
.rst ( rst )
);
endmodule
trans_pma.v
module trans_pma
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001
)
(
input clk_100M,
input tx_in, // 100M的时钟对应的数据
output tx_out,
input rst
);
reg [ 22: 0 ] scb_shift;
wire tx_tmp = tx_in ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );
reg tx_out_r = 0;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
scb_shift <= SCRAMB_SYNC;
tx_out_r <= 0;
end
else
begin
tx_out_r <= tx_tmp;
scb_shift <= { scb_shift[ 21: 0 ], tx_tmp };
end
// pmd
IO_TX IO_TX_inst
(
.tx_in ( tx_out_r ),
.tx_out ( tx_out )
);
endmodule
recv_data.v
module recv_data
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
parameter SYNC1 = 8'b1010_1010,
parameter SYNC2 = 8'b1010_1011
)
(
input rst,
input clk_100M,
input clk_400M,
input rx,
output reg sync = 0,
output reg[ 7: 0 ] rx_data_100Mr,
output reg rx_data_vld_100Mr
);
wire rx_bit;
wire rx_bit_vld;
reg rx_out_r = 0;
reg rx_out_en = 0;
reg [ 22: 0 ] scb_shift;
wire rx_tmp = rx_bit ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
rx_out_en <= 0;
scb_shift <= SCRAMB_SYNC;
rx_out_r <= 0;
end
else
begin
rx_out_en <= 0;
if( rx_bit_vld )
begin
rx_out_r <= rx_tmp;
rx_out_en <= 1;
scb_shift <= { scb_shift[ 21: 0 ], rx_bit };
end
end
reg [ 3: 0 ] bit_count;
reg [ 7: 0 ] bit_sft;
reg [ 7: 0 ] sync_shift = 0;
reg fr_sync1, fr_sync2;
reg fr_sync;
reg fr_end;
reg [ 7: 0 ] fr_count;
reg[ 7: 0 ] rx_data;
reg rx_data_vld_tmp;
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
rx_data <= 0;
rx_data_vld_tmp <= 0;
bit_count <= 0;
bit_sft <= 0;
fr_sync1 <= 0;
fr_sync2 <= 0;
fr_sync <= 0;
fr_end <= 0;
fr_count <= 0;
end
else
begin
if ( rx_out_en )
begin
bit_sft <= { rx_out_r, bit_sft[ 7: 1 ]};
sync_shift <= { bit_sft[ 0 ], sync_shift[ 7: 1] };
end
if ( fr_sync )
fr_sync2 <= 1'b0;
else if ( bit_sft == SYNC2 )
fr_sync2 <= 1'b1; //fr----frame
else
fr_sync2 <= 1'b0;
if ( fr_sync )
fr_sync1 <= 1'b0;
else if ( sync_shift == SYNC1 )
fr_sync1 <= 1'b1;
else
fr_sync1 <= 1'b0;
if ( fr_end )
fr_sync <= 1'b0;
else if ( fr_sync1 & fr_sync2 & rx_out_en )
// else if ( fr_sync1 & fr_sync2 )
fr_sync <= 1'b1;
if ( fr_sync )
begin
if ( rx_out_en )
begin
if ( bit_count == 7 )
bit_count <= 0;
else
bit_count <= bit_count + 1;
end
end
rx_data_vld_tmp <= 0;
if ( bit_count == 7 )
begin
rx_data <= bit_sft;
rx_data_vld_tmp <= 1'b1;
end
fr_end <= 1'b0;
if ( rx_data_vld_tmp & rx_out_en )
if ( fr_count == 31 )
begin
fr_end <= 1'b1;
fr_count <= 0;
end
else
fr_count <= fr_count + 1;
end
wire rx_data_vld = rx_data_vld_tmp & rx_out_en;
reg rx_data_vld_r;
reg [ 5: 0 ] count_400M;
reg rx_data_vld_x;
reg nrx_data_vld_x;
reg rx_data_vld_xrg;
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
count_400M <= 0;
rx_data_vld_r <= 0;
end
else
begin
if ( rx_data_vld )
rx_data_vld_r <= 1'b1;
else if ( count_400M == 15 )
rx_data_vld_r <= 1'b0;
if ( count_400M == 15 )
count_400M <= 0;
else if ( rx_data_vld_r )
count_400M <= count_400M + 1;
end
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
rx_data_vld_x <= 1'b0;
nrx_data_vld_x <= 1'b1;
rx_data_vld_xrg <= 1'b0;
rx_data_100Mr <= 0;
rx_data_vld_100Mr <= 1'b0;
end
else
begin
rx_data_vld_x <= rx_data_vld_r;
nrx_data_vld_x <= !rx_data_vld_x;
rx_data_vld_xrg <= nrx_data_vld_x & rx_data_vld_x;
rx_data_vld_100Mr <= 1'b0;
if ( rx_data_vld_xrg )
begin
rx_data_100Mr <= rx_data;
rx_data_vld_100Mr <= 1'b1;
end
end
always @ (posedge clk_100M)
sync <= fr_sync;
recv_bit recv_bit_inst
(
.rst ( rst ),
.clk_400M ( clk_400M ),
.rx ( rx ),
.rx_bit ( rx_bit ),
.rx_bit_vld ( rx_bit_vld )
);
endmodule
rec_pcs.v
module rev_pcs
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
parameter SYNC1 = 8'b1010_1010,
parameter SYNC2 = 8'b1010_1011
)
(
input rx,
output reg rx_vld = 0,
output rx_rdy,
output [ 7: 0 ] rx_data,
input clk_100M,
input clk_400M,
input rst
);
wire sync;
recv_data
#(
.SCRAMB_SYNC ( SCRAMB_SYNC ),
.SYNC1( SYNC1 ),
.SYNC2( SYNC2 )
)
recv_data_inst
(
.rst ( rst ),
.clk_100M ( clk_100M ),
.clk_400M ( clk_400M ),
.sync ( sync ),
.rx ( rx ),
.rx_data_100Mr ( rx_data ),
.rx_data_vld_100Mr ( rx_rdy )
);
always @ (posedge clk_100M)
if(sync) rx_vld <= 1;
else if(rx_rdy) rx_vld <= 0;
endmodule
recv_data.v
module recv_data
#(
parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
parameter SYNC1 = 8'b1010_1010,
parameter SYNC2 = 8'b1010_1011
)
(
input rst,
input clk_100M,
input clk_400M,
input rx,
output reg sync = 0,
output reg[ 7: 0 ] rx_data_100Mr,
output reg rx_data_vld_100Mr
);
wire rx_bit;
wire rx_bit_vld;
reg rx_out_r = 0;
reg rx_out_en = 0;
reg [ 22: 0 ] scb_shift;
wire rx_tmp = rx_bit ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
rx_out_en <= 0;
scb_shift <= SCRAMB_SYNC;
rx_out_r <= 0;
end
else
begin
rx_out_en <= 0;
if( rx_bit_vld )
begin
rx_out_r <= rx_tmp;
rx_out_en <= 1;
scb_shift <= { scb_shift[ 21: 0 ], rx_bit };
end
end
reg [ 3: 0 ] bit_count;
reg [ 7: 0 ] bit_sft;
reg [ 7: 0 ] sync_shift = 0;
reg fr_sync1, fr_sync2;
reg fr_sync;
reg fr_end;
reg [ 7: 0 ] fr_count;
reg[ 7: 0 ] rx_data;
reg rx_data_vld_tmp;
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
rx_data <= 0;
rx_data_vld_tmp <= 0;
bit_count <= 0;
bit_sft <= 0;
fr_sync1 <= 0;
fr_sync2 <= 0;
fr_sync <= 0;
fr_end <= 0;
fr_count <= 0;
end
else
begin
if ( rx_out_en )
begin
bit_sft <= { rx_out_r, bit_sft[ 7: 1 ]};
sync_shift <= { bit_sft[ 0 ], sync_shift[ 7: 1] };
end
if ( fr_sync )
fr_sync2 <= 1'b0;
else if ( bit_sft == SYNC2 )
fr_sync2 <= 1'b1; //fr----frame
else
fr_sync2 <= 1'b0;
if ( fr_sync )
fr_sync1 <= 1'b0;
else if ( sync_shift == SYNC1 )
fr_sync1 <= 1'b1;
else
fr_sync1 <= 1'b0;
if ( fr_end )
fr_sync <= 1'b0;
else if ( fr_sync1 & fr_sync2 & rx_out_en )
fr_sync <= 1'b1;
if ( fr_sync )
begin
if ( rx_out_en )
begin
if ( bit_count == 7 )
bit_count <= 0;
else
bit_count <= bit_count + 1;
end
end
rx_data_vld_tmp <= 0;
if ( bit_count == 7 )
begin
rx_data <= bit_sft;
rx_data_vld_tmp <= 1'b1;
end
fr_end <= 1'b0;
if ( rx_data_vld_tmp & rx_out_en )
if ( fr_count == 31 )
begin
fr_end <= 1'b1;
fr_count <= 0;
end
else
fr_count <= fr_count + 1;
end
wire rx_data_vld = rx_data_vld_tmp & rx_out_en;
reg rx_data_vld_r;
reg [ 5: 0 ] count_400M;
reg rx_data_vld_x;
reg nrx_data_vld_x;
reg rx_data_vld_xrg;
always@( posedge clk_400M or posedge rst )
if ( rst )
begin
count_400M <= 0;
rx_data_vld_r <= 0;
end
else
begin
if ( rx_data_vld )
rx_data_vld_r <= 1'b1;
else if ( count_400M == 15 )
rx_data_vld_r <= 1'b0;
if ( count_400M == 15 )
count_400M <= 0;
else if ( rx_data_vld_r )
count_400M <= count_400M + 1;
end
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
rx_data_vld_x <= 1'b0;
nrx_data_vld_x <= 1'b1;
rx_data_vld_xrg <= 1'b0;
rx_data_100Mr <= 0;
rx_data_vld_100Mr <= 1'b0;
end
else
begin
rx_data_vld_x <= rx_data_vld_r;
nrx_data_vld_x <= !rx_data_vld_x;
rx_data_vld_xrg <= nrx_data_vld_x & rx_data_vld_x;
rx_data_vld_100Mr <= 1'b0;
if ( rx_data_vld_xrg )
begin
rx_data_100Mr <= rx_data;
rx_data_vld_100Mr <= 1'b1;
end
end
always @ (posedge clk_100M)
sync <= fr_sync;
recv_bit recv_bit_inst
(
.rst ( rst ),
.clk_400M ( clk_400M ),
.rx ( rx ),
.rx_bit ( rx_bit ),
.rx_bit_vld ( rx_bit_vld )
);
endmodule
仿真波形:

图1
如图1 所示:紫色的为发送数据相关的信号, 黄色为接收相关的信号,从顶层仿真可以看出, 发送的数据可以被完整的接收到。

图2
图2所示:发送的tx_pcs 层,可以看到增加了aa,ab (preamble , sfd) 字节。

图3
如图3所示:在发送数据结束后,发送aa(preamble)。

图4
如图4所示:在接收端检测到aa,ab后(preamble ,sfd)启动fr_sync,定位数据流。 接下来就可以正常解码数据了。

图5
如图5所示:这时仿真顶层文件中, 发送第一包数据, 接收端并没有接收到, 从发送的第二包开始,之后的数据包,都可以被接收端正确接收。

图6
如图6所示:在每两包之间发送的aa (preamble) ,在线路上的编码是不同的。

图7
如图7 所示: 加扰后的波形,在局部也有可能出现直流不平衡。
具体内容讲解,请参照视频教程。
quarts 工程代码:
[content_control]
[/content_control]