DP 16bit位宽数据扰码实现和仿真
DisplayPort 1.4协议中数据需进行扰码,扰码用到了16-bit LFSR,表达式如下。
LFSR每移位8个bit后,用最高有效 8 位以相反的位顺序与一个字节数据进行异或从而实现数据加扰/解扰。
我们已利用这个框图进行8个时钟周期迭代,得到了和DP1.4协议的附录E中相同的结果。
LFSR迭代8个时钟周期输出。
R0 = b8
R1 = b9
R2 = b10
R3 = b11 ^ b8
R4 = b12 ^ b9 ^ b8
R5 = b13 ^ b10 ^ b9 ^ b8
R6 = b14 ^ b11 ^ b10 ^ b9
R7 = b15 ^ b12 ^ b11 ^ b10
R8 = b0 ^ b13 ^ b12 ^ b11
R9 = b1 ^ b14 ^ b13 ^ b12
R10 = b2 ^ b15 ^ b14 ^ b13
R11 = b3 ^ b15 ^ b14
R12 = b4 ^ b15
R13 = b5
R14 = b6
R15 = b7
利用最终输出表达式,只需1个时钟就可以得到LFSR移位后8个时钟以后的输出值。从而也就只需1个时钟就能完成8bit数据的扰码。
那如果输入数据是16bit,这时进行扰码,如何在1个时钟就能完成16bit数据的扰码呢?
我们先分析一下,16bit数据可以分成2个8bit数据,正常需要2个时钟才能完成扰码。那如果要在1个时钟内完成扰码,那么必然有1个8bit数据是与移位了16bit的LFSR的输出相异或。那么如何得到移位了16bit的LFSR的输出,是否可以将上述LFSR移位8个时钟的输出表达式迭代一次得到呢?答案是肯定的。我们来推导一下。
首先,我们先设R(n-1)时刻的输出如下。
R(n-1)0 = b8
R(n-1)1 = b9
R(n-1)2 = b10
R(n-1)3 = b11 ^ b8
R(n-1)4 = b12 ^ b9 ^ b8
R(n-1)5 = b13 ^ b10 ^ b9 ^ b8
R(n-1)6 = b14 ^ b11 ^ b10 ^ b9
R(n-1)7 = b15 ^ b12 ^ b11 ^ b10
R(n-1)8 = b0 ^ b13 ^ b12 ^ b11
R(n-1)9 = b1 ^ b14 ^ b13 ^ b12
R(n-1)10 = b2 ^ b15 ^ b14 ^ b13
R(n-1)11 = b3 ^ b15 ^ b14
R(n-1)12 = b4 ^ b15
R(n-1)13 = b5
R(n-1)14 = b6
R(n-1)15 = b7
那么R(n)时刻的输出就是如下。
R(n)0 = R(n-1)8
R(n)1 = R(n-1)9
R(n)2 = R(n-1)10
R(n)3 = R(n-1)11 ^ R(n-1)8
R(n)4 = R(n-1)12 ^ R(n-1)9 ^ R(n-1)8
R(n)5 = R(n-1)13 ^ R(n-1)10 ^ R(n-1)9 ^ R(n-1)8
R(n)6 = R(n-1)14 ^ R(n-1)11 ^ R(n-1)10 ^ R(n-1)9
R(n)7 = R(n-1)15 ^ R(n-1)12 ^ R(n-1)11 ^ R(n-1)10
R(n)8 = R(n-1)0 ^ R(n-1)13 ^ R(n-1)12 ^ R(n-1)11
R(n)9 = R(n-1)1 ^ R(n-1)14 ^ R(n-1)13 ^ R(n-1)12
R(n)10 = R(n-1)2 ^ R(n-1)15 ^ R(n-1)14 ^ R(n-1)13
R(n)11 = R(n-1)3 ^ R(n-1)15 ^ R(n-1)14
R(n)12 = R(n-1)4 ^ R(n-1)15
R(n)13 = R(n-1)5
R(n)14 = R(n-1)6
R(n)15 = R(n-1)7
最后我们再将R(n-1)时刻值用b值代入,并根据异或特性化简,去除相同项。最后得到如下结果。
R0 = b0 x b13 x b12 x b11
R1 = b1 x b14 x b13 x b12
R2 = b2 x b15 x b14 x b13
R3 = b3 x b0 x b15 x b14 x b13 x b12 x b11
R4 = b4 x b1 x b0 x b15 x b14 x b11
R5 = b5 x b2 x b1 x b0 x b15 x b13 x b11
R6 = b6 x b3 x b2 x b1 x b14 x b12
R7 = b7 x b4 x b3 x b2 x b15 x b13
R8 = b8 x b5 x b4 x b3 x b14
R9 = b9 x b6 x b5 x b4 x b15
R10 = b10 x b7 x b6 x b5
R11 = b11 x b8 x b7 x b6
R12 = b12 x b9 x b8 x b7
R13 = b13 x b10 x b9 x b8
R14 = b14 x b11 x b10 x b9
R15 = b15 x b12 x b11 x b10
然后,我们再给出LFSR按上述框图迭代16个时钟周期的输出,结果一致。
R0 = b13 x b12 x b11 x b0
R1 = b14 x b13 x b12 x b1
R2 = b15 x b14 x b13 x b2
R3 = b15 x b14 x b13 x b12 x b11 x b3 x b0
R4 = b15 x b14 x b11 x b4 x b1 x b0
R5 = b15 x b13 x b11 x b5 x b2 x b1 x b0
R6 = b14 x b12 x b6 x b3 x b2 x b1
R7 = b15 x b13 x b7 x b4 x b3 x b2
R8 = b14 x b8 x b5 x b4 x b3
R9 = b15 x b9 x b6 x b5 x b4
R10 = b10 x b7 x b6 x b5
R11 = b11 x b8 x b7 x b6
R12 = b12 x b9 x b8 x b7
R13 = b13 x b10 x b9 x b8
R14 = b14 x b11 x b10 x b9
R15 = b15 x b12 x b11 x b10
说明可以将LFSR移位8个时钟的输出表达式迭代1次就可以得到移位16个时钟的输出。那么同理,迭代2次就可以得到移位24个时钟的输出,迭代3次就可以得到移位32个时钟的输出。
接下来我们实现16bit输入数据的扰码和解码。加扰scramble模块中的LFSR采用按上述框图迭代16个时钟周期的输出。注:此代码只是用于仿真,可以方便调整输出数据中SR符号的位置,实际模块中无此功能。
module scramble #
(parameter SEQUENCY = 1'b0 //output sequency, 0:{SR,xx} // 1:{xx,SR}
)
( input I_rst_n ,//low activeinput I_sr_rst ,input I_clk ,input [1:0] I_kcode ,input [15:0] I_data ,//low byte firstoutput [1:0] O_kcode , output [15:0] O_data //scramble
);//=====================
reg [15:0] sr8_0;
reg [15:0] sr8_1; reg [7:0] scrm_byte0;//data[7:0] first
reg [7:0] scrm_byte1;//data[15:8] secondreg [1:0] I_kcode_d1;reg [1:0] scrm_kcode_d1;
reg [1:0] scrm_kcode_d2;
reg [15:0] scrm_data_d1;
reg [15:0] scrm_data_d2;//====================
always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) beginI_kcode_d1 <= 2'b0;endelsebeginI_kcode_d1 <= I_kcode;end
end//=====================
//LFSR 并行结构,16次移位后
always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) sr8_0 <= 16'hffff ; //16'hfffe ;16'hffff ;else if(I_sr_rst)sr8_0 <= 16'hffff ; //16'hfffe ;16'hffff ;elsebegin sr8_0[ 0] <= sr8_0[ 0] ^ sr8_0[13] ^ sr8_0[12] ^ sr8_0[11]; sr8_0[ 1] <= sr8_0[ 1] ^ sr8_0[14] ^ sr8_0[13] ^ sr8_0[12]; sr8_0[ 2] <= sr8_0[ 2] ^ sr8_0[15] ^ sr8_0[14] ^ sr8_0[13]; sr8_0[ 3] <= sr8_0[ 3] ^ sr8_0[ 0] ^ sr8_0[15] ^ sr8_0[14] ^ sr8_0[13] ^ sr8_0[12] ^ sr8_0[11]; sr8_0[ 4] <= sr8_0[ 4] ^ sr8_0[ 1] ^ sr8_0[ 0] ^ sr8_0[15] ^ sr8_0[14] ^ sr8_0[11]; sr8_0[ 5] <= sr8_0[ 5] ^ sr8_0[ 2] ^ sr8_0[ 1] ^ sr8_0[ 0] ^ sr8_0[15] ^ sr8_0[13] ^ sr8_0[11]; sr8_0[ 6] <= sr8_0[ 6] ^ sr8_0[ 3] ^ sr8_0[ 2] ^ sr8_0[ 1] ^ sr8_0[14] ^ sr8_0[12]; sr8_0[ 7] <= sr8_0[ 7] ^ sr8_0[ 4] ^ sr8_0[ 3] ^ sr8_0[ 2] ^ sr8_0[15] ^ sr8_0[13]; sr8_0[ 8] <= sr8_0[ 8] ^ sr8_0[ 5] ^ sr8_0[ 4] ^ sr8_0[ 3] ^ sr8_0[14]; sr8_0[ 9] <= sr8_0[ 9] ^ sr8_0[ 6] ^ sr8_0[ 5] ^ sr8_0[ 4] ^ sr8_0[15]; sr8_0[10] <= sr8_0[10] ^ sr8_0[ 7] ^ sr8_0[ 6] ^ sr8_0[ 5]; sr8_0[11] <= sr8_0[11] ^ sr8_0[ 8] ^ sr8_0[ 7] ^ sr8_0[ 6]; sr8_0[12] <= sr8_0[12] ^ sr8_0[ 9] ^ sr8_0[ 8] ^ sr8_0[ 7]; sr8_0[13] <= sr8_0[13] ^ sr8_0[10] ^ sr8_0[ 9] ^ sr8_0[ 8]; sr8_0[14] <= sr8_0[14] ^ sr8_0[11] ^ sr8_0[10] ^ sr8_0[ 9]; sr8_0[15] <= sr8_0[15] ^ sr8_0[12] ^ sr8_0[11] ^ sr8_0[10]; end
end always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) sr8_1 <= 16'he817 ; //16'he917 ;16'he817 ;else if(I_sr_rst)sr8_1 <= 16'he817 ; //16'he917 ;16'he817 ;elsebegin sr8_1[ 0] <= sr8_1[ 0] ^ sr8_1[13] ^ sr8_1[12] ^ sr8_1[11]; sr8_1[ 1] <= sr8_1[ 1] ^ sr8_1[14] ^ sr8_1[13] ^ sr8_1[12]; sr8_1[ 2] <= sr8_1[ 2] ^ sr8_1[15] ^ sr8_1[14] ^ sr8_1[13]; sr8_1[ 3] <= sr8_1[ 3] ^ sr8_1[ 0] ^ sr8_1[15] ^ sr8_1[14] ^ sr8_1[13] ^ sr8_1[12] ^ sr8_1[11]; sr8_1[ 4] <= sr8_1[ 4] ^ sr8_1[ 1] ^ sr8_1[ 0] ^ sr8_1[15] ^ sr8_1[14] ^ sr8_1[11]; sr8_1[ 5] <= sr8_1[ 5] ^ sr8_1[ 2] ^ sr8_1[ 1] ^ sr8_1[ 0] ^ sr8_1[15] ^ sr8_1[13] ^ sr8_1[11]; sr8_1[ 6] <= sr8_1[ 6] ^ sr8_1[ 3] ^ sr8_1[ 2] ^ sr8_1[ 1] ^ sr8_1[14] ^ sr8_1[12]; sr8_1[ 7] <= sr8_1[ 7] ^ sr8_1[ 4] ^ sr8_1[ 3] ^ sr8_1[ 2] ^ sr8_1[15] ^ sr8_1[13]; sr8_1[ 8] <= sr8_1[ 8] ^ sr8_1[ 5] ^ sr8_1[ 4] ^ sr8_1[ 3] ^ sr8_1[14]; sr8_1[ 9] <= sr8_1[ 9] ^ sr8_1[ 6] ^ sr8_1[ 5] ^ sr8_1[ 4] ^ sr8_1[15]; sr8_1[10] <= sr8_1[10] ^ sr8_1[ 7] ^ sr8_1[ 6] ^ sr8_1[ 5]; sr8_1[11] <= sr8_1[11] ^ sr8_1[ 8] ^ sr8_1[ 7] ^ sr8_1[ 6]; sr8_1[12] <= sr8_1[12] ^ sr8_1[ 9] ^ sr8_1[ 8] ^ sr8_1[ 7]; sr8_1[13] <= sr8_1[13] ^ sr8_1[10] ^ sr8_1[ 9] ^ sr8_1[ 8]; sr8_1[14] <= sr8_1[14] ^ sr8_1[11] ^ sr8_1[10] ^ sr8_1[ 9]; sr8_1[15] <= sr8_1[15] ^ sr8_1[12] ^ sr8_1[11] ^ sr8_1[10]; end
end //=====================
always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) scrm_byte0 <= 8'd0 ; else if(I_kcode[0] == 1'b0)begin scrm_byte0[ 0] <= I_data[ 0] ^ sr8_0[15];scrm_byte0[ 1] <= I_data[ 1] ^ sr8_0[14];scrm_byte0[ 2] <= I_data[ 2] ^ sr8_0[13];scrm_byte0[ 3] <= I_data[ 3] ^ sr8_0[12]; scrm_byte0[ 4] <= I_data[ 4] ^ sr8_0[11];scrm_byte0[ 5] <= I_data[ 5] ^ sr8_0[10]; scrm_byte0[ 6] <= I_data[ 6] ^ sr8_0[ 9]; scrm_byte0[ 7] <= I_data[ 7] ^ sr8_0[ 8]; end elsescrm_byte0 <= I_data[7:0];
end always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) scrm_byte1 <= 8'd0 ; else if(I_kcode[1] == 1'b0)begin scrm_byte1[ 0] <= I_data[ 8] ^ sr8_1[15];scrm_byte1[ 1] <= I_data[ 9] ^ sr8_1[14];scrm_byte1[ 2] <= I_data[10] ^ sr8_1[13];scrm_byte1[ 3] <= I_data[11] ^ sr8_1[12]; scrm_byte1[ 4] <= I_data[12] ^ sr8_1[11];scrm_byte1[ 5] <= I_data[13] ^ sr8_1[10]; scrm_byte1[ 6] <= I_data[14] ^ sr8_1[ 9]; scrm_byte1[ 7] <= I_data[15] ^ sr8_1[ 8]; end elsescrm_byte1 <= I_data[15:8];
end //----------------------
always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) beginscrm_kcode_d1 <= 2'd0;scrm_kcode_d2 <= 2'd0;scrm_data_d1 <= 16'd0;scrm_data_d2 <= 16'd0;endelsebeginscrm_kcode_d1 <= I_kcode_d1;scrm_kcode_d2 <= scrm_kcode_d1;scrm_data_d1 <= {scrm_byte1,scrm_byte0};scrm_data_d2 <= scrm_data_d1;end
endassign O_kcode = (SEQUENCY == 1'b0) ? scrm_kcode_d2 :(SEQUENCY == 1'b1) ? {scrm_kcode_d1[0],scrm_kcode_d2[1]} : scrm_kcode_d2;
assign O_data = (SEQUENCY == 1'b0) ? scrm_data_d2 :(SEQUENCY == 1'b1) ? {scrm_data_d1[7:0],scrm_data_d2[15:8]} : scrm_data_d2;endmodule
解扰descramble模块中的LFSR采用根据DP协议附录中参考代码并行迭代一次输出。因为加扰和解扰使用的是相同的电路结构,所以此解扰descramble模块也可以做加扰scramble模块使用。此代码可以在实际应用中使用。
module descramble
( input I_rst_n ,//low activeinput I_clk ,input [16/8-1:0] I_kcode ,input [16-1:0] I_data ,//low byte firstoutput [16/8-1:0] O_kcode , output [16-1:0] O_data
);localparam SR_SYM = 8'h1C; //K28.0localparam N = 2;// Symbols per lane//=====================
wire[15:0] sri[0:1];//两组LFSR 级联
reg [15:0] sro[0:1];
reg [15:0] sro_hi; wire[1:0] k_in;
wire[7:0] d_in[0:1]; //数据按字节分组wire[1:0] sr_symbl;
wire[1:0] sr_reset; reg [1:0] k_out;
reg [7:0] d_out[0:1];genvar i;
integer j;//====================
assign k_in[0] = I_kcode[0];
assign k_in[1] = I_kcode[1];
assign d_in[0] = I_data[ 7: 0];
assign d_in[1] = I_data[15: 8];//=====================
//SR symbol detect
assign sr_reset[0] = (k_in[0] & (d_in[0] == SR_SYM)) ? 1'b1 : 1'b0;
assign sr_reset[1] = (k_in[1] & (d_in[1] == SR_SYM)) ? 1'b1 : 1'b0;//=====================
//LFSR 并行结构,参考DP协议手册
assign sri[0] = sro_hi;
assign sri[1] = sro[0];// LFSR
always@(*)
begin if(sr_reset[0])sro[0] <= 16'hffff ; //16'hfffe ;16'hffff ;elsebegin sro[0][ 0] <= sri[0][ 8]; sro[0][ 1] <= sri[0][ 9]; sro[0][ 2] <= sri[0][10]; sro[0][ 3] <= sri[0][11] ^ sri[0][ 8]; sro[0][ 4] <= sri[0][12] ^ sri[0][ 9] ^ sri[0][ 8]; sro[0][ 5] <= sri[0][13] ^ sri[0][10] ^ sri[0][ 9] ^ sri[0][ 8]; sro[0][ 6] <= sri[0][14] ^ sri[0][11] ^ sri[0][10] ^ sri[0][ 9]; sro[0][ 7] <= sri[0][15] ^ sri[0][12] ^ sri[0][11] ^ sri[0][10]; sro[0][ 8] <= sri[0][ 0] ^ sri[0][13] ^ sri[0][12] ^ sri[0][11]; sro[0][ 9] <= sri[0][ 1] ^ sri[0][14] ^ sri[0][13] ^ sri[0][12]; sro[0][10] <= sri[0][ 2] ^ sri[0][15] ^ sri[0][14] ^ sri[0][13]; sro[0][11] <= sri[0][ 3] ^ sri[0][15] ^ sri[0][14]; sro[0][12] <= sri[0][ 4] ^ sri[0][15]; sro[0][13] <= sri[0][ 5]; sro[0][14] <= sri[0][ 6]; sro[0][15] <= sri[0][ 7]; end
end always@(*)
begin if(sr_reset[1])sro[1] <= 16'hffff ; //16'hfffe ;16'hffff ;elsebegin sro[1][ 0] <= sri[1][ 8]; sro[1][ 1] <= sri[1][ 9]; sro[1][ 2] <= sri[1][10]; sro[1][ 3] <= sri[1][11] ^ sri[1][ 8]; sro[1][ 4] <= sri[1][12] ^ sri[1][ 9] ^ sri[1][ 8]; sro[1][ 5] <= sri[1][13] ^ sri[1][10] ^ sri[1][ 9] ^ sri[1][ 8]; sro[1][ 6] <= sri[1][14] ^ sri[1][11] ^ sri[1][10] ^ sri[1][ 9]; sro[1][ 7] <= sri[1][15] ^ sri[1][12] ^ sri[1][11] ^ sri[1][10]; sro[1][ 8] <= sri[1][ 0] ^ sri[1][13] ^ sri[1][12] ^ sri[1][11]; sro[1][ 9] <= sri[1][ 1] ^ sri[1][14] ^ sri[1][13] ^ sri[1][12]; sro[1][10] <= sri[1][ 2] ^ sri[1][15] ^ sri[1][14] ^ sri[1][13]; sro[1][11] <= sri[1][ 3] ^ sri[1][15] ^ sri[1][14]; sro[1][12] <= sri[1][ 4] ^ sri[1][15]; sro[1][13] <= sri[1][ 5]; sro[1][14] <= sri[1][ 6]; sro[1][15] <= sri[1][ 7]; end
end always@(posedge I_clk or negedge I_rst_n)
begin if(!I_rst_n) sro_hi <= 16'd0;elsesro_hi = sro[1];
end//=====================
generatefor (i = 0; i < N; i=i+1)begin : gen_scrm_doutalways@(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) d_out[i] <= 8'd0;else if(k_in[i] == 1'b0)for (j = 0; j < 8; j=j+1)begin d_out[i][j] <= d_in[i][j] ^ sri[i][15-j];end elsed_out[i] <= d_in[i];end always@(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) k_out[i] <= 1'b0;elsek_out[i] <= k_in[i];endend
endgenerate assign O_kcode[0] = k_out[0];
assign O_kcode[1] = k_out[1];
assign O_data[ 7: 0] = d_out[0];
assign O_data[15: 8] = d_out[1];endmodule
仿真工程如下地址下载https://download.csdn.net/download/cjie221/90623678
仿真波形如下,经过加扰后再解扰,最终数据与原始数据一致。