在课程高速通信中的信道编码–加扰与解扰 中,我们学习了乘性加扰的算法,但不是一个完整的通讯工程。之前我们学习过使用400M时钟对100M的通讯数据采样,学习过400M下的得到的数据如何同步到100M时钟域下。利用我们之前学习过的知识,增加乘性加扰,解扰算法,就可以实现整个通讯工程了。
仿真文件:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
`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 文件相同。
顶层文件:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
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]