在上节内容中讲解了串行通信中的帧结构,如每个帧的开始部分都会有前导字和帧起始(即Preamble+SFD)作为帧的标志,在帧同步时作为同步字搜索,接收端可以在搜索到关键字后进行帧同步。这个前导字不仅能提供短暂的直流平衡,还能提供足够的时钟信息,在位同步的解调中起到关键的作用。在自适应位同步的提取中(ACDR),有一个前提是在帧数据部分也应该有足够的边沿变化,而在源码的数据流中长0或长1的概率是非常高的,因此就要将通信中的源码进行变换,通常称为编码。这种用于改善信道的编码称为信道编码。信道编码通常有如下几种,加扰,4b/5b编码,8b/10b编码,64b/66b编码,128b/130b, 128b/132b等,其它几种编码已经在其它章节介绍过了,本节内容着重讲解加扰(Scrambler)编码以及其反变换–解扰(de-scrambler)等原理及使用。
1. 加扰
加扰的原理是在数据串行化时将串行数据流送入加扰器,通过加扰器的模2运算(异或运算)使得长0与长1消除。关于加扰的原理的相关知识,可以参考相关内容。加扰又分为两种,加性加扰和乘性加扰两种。加性加扰如图1所示,

图1 加性加扰器
- 加性加扰
加性加扰的特点是加扰器产生的模2运算的结果与输入数据再做模2运算,结果作为串行数据输出。加性加扰器有如下内容及特点:
(1)典型生成多项式 ,
G(X) = X15 + X14 + 1
G(X) = X23 + X18 + 1
(2) 运算前需要同步,即在一帧数据发送前应初始化加扰器如图1,在帧数据加扰前应将加扰器的寄存器初始化为1001_0101_0000_000, 例如
reg [14:0] sramb_sync = 15’b000_0000_1010_1001;
(3)输入数据不参与加扰器的寄存器移位,仅加扰器自身的模2加结果参与循环移位
(4)解扰器的生成多项式即运算过程与加扰器一致如图1,解扰器也需要帧初始化同步。同步控制一般采用帧起始(如preamble+SFD)或64b/66b的中66-bit的控制位(如01或10, 详细内容请参照64b/66b的内容).
例1, 利用生成多项式G(X) = X15 + X14 + 1 实现加性加扰与解码Verilog代码,并通过Modelsim进行验证。
发送端代码:
|
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 |
`timescale 1 ns /1 ps module additive_scrambler_tx# ( parameter SCRAMB_SYNC = 15'b000_0000_1010_1001 ) ( input sys_clk, input rst, input tx_start, input tx_en, input [ 7: 0 ] tx_data, input tx_end, output reg tx_rdy, output reg tx_out ); reg [ 14: 0 ] scrambler; reg [ 7: 0 ] tx_shift; reg [ 3: 0 ] shift_count; wire scb_bit; reg tx_end_r; reg tx_end_ack; always@( posedge sys_clk or posedge rst ) if ( rst ) tx_end_r <= 0; else begin if ( tx_end ) tx_end_r <= 1'b1; else if ( tx_end_ack ) tx_end_r <= 1'b0; end reg [ 2: 0 ] scb_st; assign scb_bit = scrambler[ 14 ] ^ scrambler[ 13 ]; always@( posedge sys_clk or posedge rst ) if ( rst ) begin scb_st <= 0; scrambler <= SCRAMB_SYNC; tx_shift <= 0; shift_count <= 0; tx_rdy <= 0; tx_end_ack <= 0; end else begin case ( scb_st ) 0: begin tx_rdy <= 1'b0; tx_end_ack <= 0; if ( tx_start ) begin scb_st <= 1; scrambler <= SCRAMB_SYNC; end end 1: begin tx_rdy <= 1'b1; shift_count <= 0; if ( tx_end ) scb_st <= 0; else if ( tx_en ) begin tx_shift <= tx_data; shift_count <= shift_count + 1; tx_rdy <= 1'b0; scb_st <= 2; end end 2: begin tx_rdy <= 0; scrambler <= { scrambler[ 13: 0 ], scb_bit }; if ( tx_en ) begin tx_shift <= tx_data; end else tx_shift <= { 1'b1, tx_shift[ 7: 1 ] }; if ( shift_count == 6 ) tx_rdy <= 1'b1; if ( shift_count == 7 ) begin shift_count <= 0; if ( tx_end_r ) begin scb_st <= 0; tx_end_ack <= 1; end end else shift_count <= shift_count + 1; end default: scb_st <= 0; endcase end always@( posedge sys_clk or posedge rst ) if ( rst ) begin tx_out <= 1'b1; end else begin tx_out <= tx_shift[ 0 ] ^ scb_bit; end endmodule |
接收端代码:
|
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 |
`timescale 1 ns /1 ps module additive_scrambler_rx# ( parameter SCRAMB_SYNC = 15'b000_0000_1010_1001 ) ( input sys_clk, input rst, input rx_start, input rx_en, input rx_in, input rx_end, output reg rx_rdy, output reg [ 7: 0 ] rx_data ); reg [ 14: 0 ] scrambler; reg [ 7: 0 ] rx_shift; reg [ 3: 0 ] shift_count; wire scb_bit; wire rx_bit; reg rx_rdy_tmp; reg rx_end_r; reg rx_end_ack; reg [ 2: 0 ] scb_st; assign scb_bit = scrambler[ 14 ] ^ scrambler[ 13 ]; assign rx_bit = rx_in ^ scb_bit; always@( posedge sys_clk or posedge rst ) if ( rst ) rx_end_r <= 0; else if ( rx_end ) rx_end_r <= 1'b1; else if ( rx_end_ack ) rx_end_r <= 1'b0; always@( posedge sys_clk or posedge rst ) if ( rst ) begin scb_st <= 0; scrambler <= SCRAMB_SYNC; rx_shift <= 0; shift_count <= 0; rx_rdy_tmp <= 0; rx_end_ack <= 1'b0; end else begin case ( scb_st ) 0: begin rx_rdy_tmp <= 0; rx_end_ack <= 1'b0; if ( rx_start ) begin scb_st <= 1; scrambler <= SCRAMB_SYNC; end end 1: begin rx_rdy_tmp <= 0; if ( rx_end ) scb_st <= 0; else if ( rx_en ) begin scb_st <= 2; end end 2: begin rx_rdy_tmp <= 1'b0; scrambler <= { scrambler[ 13: 0 ], scb_bit }; rx_shift <= { rx_bit, rx_shift[ 7: 1 ] }; if ( shift_count == 7 ) begin shift_count <= 0; rx_rdy_tmp <= 1'b1; if ( rx_end_r ) begin rx_end_ack <= 1'b1; scb_st <= 0; end end else shift_count <= shift_count + 1; end default: scb_st <= 0; endcase end always@( posedge sys_clk or posedge rst ) if ( rst ) begin rx_data <= 0; rx_rdy <= 0; end else begin rx_rdy <= rx_rdy_tmp; if ( rx_rdy_tmp ) begin rx_data <= rx_shift; end end endmodule |
发送接收组装代码:
|
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 |
`timescale 1 ns /1 ps module additive_scrambler# ( parameter SCRAMB_SYNC = 15'b000_0000_1010_1001 ) ( input sys_clk, input rst, input tx_start, input tx_en, input [ 7: 0 ] tx_data, input tx_end, output tx_rdy, output [ 7: 0 ] rx_data, output rx_rdy ); wire tx_out; reg rx_en; wire rx_in = tx_out; //回环测试 always@( posedge sys_clk or posedge rst ) if ( rst ) begin rx_en <= 0; end else begin if ( tx_end ) rx_en <= 0; else if ( tx_en ) rx_en <= 1'b1; end additive_scrambler_tx# ( .SCRAMB_SYNC( 15'b000_0000_1010_1001 ) ) additive_scrambler_tx_inst ( .sys_clk ( sys_clk ), .rst ( rst ), .tx_start ( tx_start ), .tx_en ( tx_en ), .tx_data ( tx_data ), .tx_end ( tx_end ), .tx_rdy ( tx_rdy ), .tx_out ( tx_out ) ); additive_scrambler_rx# ( .SCRAMB_SYNC( 15'b000_0000_1010_1001 ) ) additive_scrambler_rx_inst ( .sys_clk ( sys_clk ), .rst ( rst ), .rx_start ( tx_start ), .rx_en ( rx_en ), .rx_in ( rx_in ), .rx_end ( tx_end ), .rx_data ( rx_data ), .rx_rdy ( rx_rdy ) ); endmodule |
仿真代码:
|
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 |
`timescale 1 ns /1 ps module tb ( ); parameter sramb_sync = 15'b000_0000_1010_1001; reg sys_clk = 0; always #5 sys_clk = ~sys_clk; reg rst = 1'b1; initial begin rst = 1'b1; #15 rst = 1'b0; end wire [ 7: 0 ] rx_data; wire rx_rdy; //=====================additive scambler wire tx_rdy; reg [ 7: 0 ] tx_data; reg tx_start; reg tx_en; reg tx_end; reg [ 4: 0 ] tx_delay; reg [ 7: 0 ] tx_count; reg [ 1: 0 ] tx_st; always@( posedge sys_clk or posedge rst ) if ( rst ) begin tx_data <= 0; tx_count <= 0; tx_en <= 0; tx_start <= 0; tx_delay <= 0; tx_end <= 0; tx_st <= 0; end else begin case ( tx_st ) 0: begin tx_start <= 1'b1; tx_data <= 0; tx_count <= 0; tx_en <= 0; tx_delay <= 0; tx_st <= 1; end 1: begin tx_start <= 1'b0; if ( tx_rdy ) begin tx_count <= tx_count + 1; tx_en <= 1'b1; tx_st <= 2; end end 2: begin tx_en <= 0; if ( tx_count == 32 ) begin tx_end <= 1'b1; tx_st <= 3; end else begin // tx_count <= tx_count + 1; tx_st <= 1; end if ( tx_count < 8 ) tx_data <= 0; else if ( tx_count > 23 ) tx_data <= 8'hff; else tx_data <= tx_count; end 3: begin tx_end <= 0; if ( tx_delay == 31 ) tx_st <= 0; else tx_delay <= tx_delay + 1; end endcase end additive_scrambler# ( .SCRAMB_SYNC( 15'b000_0000_1010_1001 ) ) additive_scrambler_inst ( .sys_clk ( sys_clk ), .rst ( rst ), .tx_start ( tx_start ), .tx_en ( tx_en ), .tx_data ( tx_data ), .tx_end ( tx_end ), .tx_rdy ( tx_rdy ), .rx_data ( rx_data ), .rx_rdy ( rx_rdy ) ); endmodule |

图1 tb仿真波形
图1 可以看出在加扰后接系统能正确解扰收发端的加扰数据,详细的加扰效果可以参考图2。

图2
图2 中显示了发送程序的加扰效果,红色框中在tx_data在一段时间都为0,但tx_out信号经过加扰后,出现0,1交替输出。

图3
图3中可以观察到在接收端rx_in, scb_bit, rx_bit之间的运算,以及scrambler 的移位过程。
上面的例子主要目的是演示了加扰后对发送串行流带来的效果,如图2, 同时对于加性加扰如何根据帧同步控制加扰器进行复位初始化,以及在发送和接收中实现加扰/解扰器的移位。在实际的异步通信中可以用Preamble+SFD实现帧同步,或采用64b/66b的2位控制字实现同步。
- 乘性加扰
与加性加扰不同的是乘性加扰不仅加扰器自身模2加后循环移位,而且输入数据流也参与模2运算后参与加扰计算,从这一点看数据流的输出与输入之间(历史数据)有相与的关系存在,因此称为乘性加扰。生成多项式为G(X) = X23 + X18 + 1的加扰器如图4所示。
乘性加扰是递归的。即加扰后的信号反馈到移位回路中。

图4
- 乘性解扰
与加性解扰不同,乘性解扰不需要同步和初始化,但乘性解扰不能使用加扰器进行解扰,这一点与加性加扰器有重大区别,从上的加性加扰和解扰可以看出,加性加扰与解扰使用同一套加扰器。而乘性解扰则是独立的逻辑电路,如图5所示。

图5
解扰器的特点是非递归的,即解扰后的信号不反馈到回路中去。
2 .乘性加扰与加性加扰相比有如下异同点:
-
- 加性加扰需要特定初始化值,乘性加扰不需要特定初始化值(可以为随机数)。
- 加性加扰需要同步复位,乘性加扰不需要同步复位
- 加性加扰器也加性解扰器,乘性加扰与解扰分别为不同时序逻辑电路,但生成多项式相同。
- 加性加扰循环移位寄存器不受输入信号的影响是移位寄存器模2运算移位的结果,乘性加扰器的输入参与模2运算并前馈到移位序列中,历史输入数据参与加扰运算。
- 乘性加扰由于不需要同步复位,因此在加扰和解扰时的逻辑设计相对简单。
3. 乘性加扰与解扰编程与测试
(1) 发送端乘性加扰物理层(phy)的代码mul_scrambler_phy.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 |
`timescale 1 ns /1 ps module mul_scrambler_phy ( input rst, input sys_clk, input tx_in, output reg tx_out ); reg [ 22: 0 ] scb_shift; wire tx_tmp = tx_in ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] ); always@( posedge sys_clk or posedge rst ) if ( rst ) begin scb_shift <= 0; tx_out <= 0; end else begin tx_out <= tx_tmp; scb_shift <= { scb_shift[ 21: 0 ], tx_tmp }; end endmodule |
(2)接收端端乘性加扰物理层(phy)的代码mul_scrambler_phy.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 |
`timescale 1 ns /1 ps module mul_descrambler_phy ( input rst, input sys_clk, input rx_in, output reg rx_out ); reg [ 22: 0 ] scb_shift; wire rx_tmp = rx_in ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] ); always@( posedge sys_clk or posedge rst ) if ( rst ) begin scb_shift <= 0; rx_out <= 0; end else begin rx_out <= rx_tmp; scb_shift <= { scb_shift[ 21: 0 ], rx_in }; end endmodule |
(3)发送端数据帧及串行化mul_scrambler.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 |
`timescale 1 ns /1 ps module mul_scrambler# ( parameter SYNC_PREABLE = 8'b1010_1010, parameter SYNC_SFD = 8'b1010_1011 ) ( input rst, input sys_clk, input tx_start, input [ 7: 0 ] tx_data, input tx_en, input tx_end, output reg tx_rdy_r, output tx_out ); reg [ 7: 0 ] tx_data_r; reg [ 7: 0 ] tx_sht; reg [ 2: 0 ] tx_sht_count; reg [ 2: 0 ] tx_st; wire tx_bit = tx_sht[ 7 ]; reg tx_start_r; reg tx_start_ack; reg tx_en_r; reg tx_en_ack; reg tx_end_r; reg tx_end_ack; reg tx_rdy; always@( posedge sys_clk or posedge rst ) if ( rst ) begin tx_start_r <= 0; tx_end_r <= 0; tx_en_r <= 0; tx_rdy_r <= 0; end else begin if ( tx_start ) tx_start_r <= 1'b1; else if ( tx_start_ack ) tx_start_r <= 1'b0; if ( tx_end ) tx_end_r <= 1'b1; else if ( tx_end_ack ) tx_end_r <= 1'b0; if ( tx_en ) tx_en_r <= 1'b1; else if ( tx_en_ack ) tx_en_r <= 0; tx_rdy_r <= tx_rdy; end always@( posedge sys_clk or posedge rst ) if ( rst ) begin tx_data_r <= SYNC_PREABLE; tx_sht <= SYNC_PREABLE; tx_sht_count <= 0; tx_rdy <= 1'b0; tx_start_ack <= 0; tx_end_ack <= 1'b0; tx_en_ack <= 1'b0; tx_st <= 0; end else begin case ( tx_st ) 0: begin tx_data_r <= SYNC_PREABLE; tx_sht <= tx_data_r; tx_sht_count <= 0; tx_rdy <= 1'b0; tx_start_ack <= 0; tx_end_ack <= 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_start_r ) begin tx_data_r <= SYNC_SFD; tx_start_ack <= 1'b1; tx_en_ack <= 1'b1; tx_rdy <= 1'b1; tx_st <= 2; end end else begin tx_sht <= { tx_sht[ 6: 0 ], 1'b0 }; tx_sht_count <= tx_sht_count + 1'b1; end end 2: begin tx_en_ack <= 1'b0; tx_rdy <= 1'b0; tx_start_ack <= 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_end_r ) begin tx_end_ack <= 1'b1; tx_en_ack <= 1'b1; tx_data_r <= SYNC_PREABLE; tx_sht <= SYNC_PREABLE; tx_st <= 0; end end else begin tx_sht <= { tx_sht[ 6: 0 ], 1'b0 }; tx_sht_count <= tx_sht_count + 1'b1; end end default: tx_st <= 0; endcase end mul_scrambler_phy mul_scrambler_phy ( .rst ( rst ), .sys_clk ( sys_clk ), .tx_in ( tx_bit ), .tx_out ( tx_out ) ); endmodule |
(4)接收端串并转换及数据帧mul_descrambler.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 |
`timescale 1 ns /1 ps module mul_descrambler# ( parameter SYNC_PREABLE = 8'b1010_1010, parameter SYNC_SFD = 8'b1010_1011 ) ( input rst, input sys_clk, input rx_in, output reg[ 7: 0 ] rx_data, output reg rx_rdy, output reg fr_end ); wire rx_out; reg [ 4: 0 ] rx_count; reg [ 2: 0 ] rx_bit_count; reg [ 7: 0 ] bit_sft; reg [ 7: 0 ] sync_shift; reg fr_sync; always@( posedge sys_clk or posedge rst ) if ( rst ) begin bit_sft <= 0; sync_shift <= 0; rx_data <= 0; rx_rdy <= 1'b0; rx_bit_count <= 0; rx_count <= 0; fr_sync <= 0; fr_end <= 0; end else begin bit_sft <= { bit_sft[ 6: 0 ], rx_out }; sync_shift <= { sync_shift[ 6: 0 ], bit_sft[ 7 ] }; if ( fr_end ) begin fr_sync <= 1'b0; end else if ( ( bit_sft == SYNC_SFD ) && ( sync_shift == SYNC_PREABLE ) ) fr_sync <= 1'b1; rx_rdy <= 1'b0; if ( fr_sync ) begin if ( rx_bit_count == 7 ) begin rx_rdy <= 1'b1; rx_data <= bit_sft; rx_bit_count <= 0; end else rx_bit_count <= rx_bit_count + 1; end fr_end <= 0; if ( fr_end ) rx_bit_count <= 0; else if ( rx_rdy ) begin if ( rx_count == 31 ) begin rx_count <= 0; fr_end <= 1'b1; end else rx_count <= rx_count + 1; end end mul_descrambler_phy mul_descrambler_phy_inst ( .rst ( rst ), .sys_clk ( sys_clk ), .rx_in ( rx_in ), .rx_out ( rx_out ) ); endmodule |
(5)收发合并comp_mul_scrabler.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 |
`timescale 1 ns /1 ps module comp_mul_scrabler# ( parameter SYNC_PREABLE = 8'b1010_1010, parameter SYNC_SFD = 8'b1010_1011 ) ( input rst, input sys_clk, input tx_start, output tx_rdy, input [ 7: 0 ] tx_data, input tx_en, input tx_end, output rx_vld, output[ 7: 0 ] rx_data, output rx_rdy, output fr_end ); wire tx_bit; mul_scrambler# ( .SYNC_PREABLE( SYNC_PREABLE ), .SYNC_SFD ( SYNC_SFD ) ) mul_scrambler_inst ( .rst ( rst ), .sys_clk ( sys_clk ), .tx_start ( tx_start ), .tx_data ( tx_data ), .tx_en ( tx_en ), .tx_end ( tx_end ), .tx_rdy_r ( tx_rdy ), .tx_out ( tx_bit ) ); mul_descrambler# ( .SYNC_PREABLE( SYNC_PREABLE ), .SYNC_SFD ( SYNC_SFD ) ) mul_descrambler_inst ( .rst ( rst ), .sys_clk ( sys_clk ), .rx_in ( tx_bit ), // feedback loop .rx_data ( rx_data ), .fr_end ( fr_end ), .rx_rdy ( rx_rdy ) ); endmodule |
(6)仿真程序tb.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 |
`timescale 1 ns /1 ps module tb ( ); parameter sramb_sync = 15'b000_0000_1010_1001; reg sys_clk = 0; always #5 sys_clk = ~sys_clk; reg rst = 1'b1; initial begin rst = 1'b1; #15 rst = 1'b0; end wire [ 7: 0 ] rx_data; wire rx_rdy; //=====================additive scambler wire tx_rdy; reg [ 7: 0 ] tx_data; reg tx_start; reg tx_en; reg tx_end; reg [ 4: 0 ] tx_delay; reg [ 7: 0 ] tx_count; reg [ 1: 0 ] tx_st; always@( posedge sys_clk or posedge rst ) if ( rst ) begin tx_data <= 0; tx_count <= 0; tx_en <= 0; tx_start <= 0; tx_delay <= 0; tx_end <= 0; tx_st <= 0; end else begin case ( tx_st ) 0: begin tx_start <= 1'b1; tx_data <= 0; tx_count <= 0; tx_en <= 0; tx_delay <= 0; tx_st <= 1; end 1: begin tx_start <= 1'b0; if ( tx_rdy ) begin tx_en <= 1'b1; tx_st <= 2; end end 2: begin tx_en <= 0; if ( tx_count == 32 ) begin tx_end <= 1'b1; tx_st <= 3; end else begin tx_count <= tx_count + 1; tx_st <= 1; end if ( tx_count < 8 ) tx_data <= 0; else if ( tx_count > 23 ) tx_data <= 8'hff; else tx_data <= tx_count; end 3: begin tx_end <= 0; if ( tx_delay == 31 ) tx_st <= 0; else tx_delay <= tx_delay + 1; end endcase end additive_scrambler# ( .SCRAMB_SYNC( 15'b000_0000_1010_1001 ) ) additive_scrambler_inst ( .sys_clk ( sys_clk ), .rst ( rst ), .tx_start ( tx_start ), .tx_en ( tx_en ), .tx_data ( tx_data ), .tx_end ( tx_end ), .tx_rdy ( tx_rdy ), .rx_data ( rx_data ), .rx_rdy ( rx_rdy ) ); endmodule |
(7) 仿真波形

图6 tb.v的仿真波形

图7 mul_scrambler.v 仿真波形

图8 mul_descrambler.v的仿真波形
乘性加扰及解扰工程代码下载:
[content_control]
[/content_control]
注:加性加扰,将上文中的第一个tb.v替代工程中的tb.v文件即可测试加性加扰/解扰的Verilog RTL 代码。更详细的解释请看对应的视频文件。