当前位置: 首页 > news >正文

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
  仿真波形如下,经过加扰后再解扰,最终数据与原始数据一致。
在这里插入图片描述

相关文章:

  • 淘宝大数据接口解析:商品类目 / 价格 / 销量多维数据采集与存储方案
  • 软件测试——BUG概念
  • Uniapp权限申请优化方案
  • Browser-use 是连接你的AI代理与浏览器的最简单方式
  • 什么是跨域问题以及其解决方案
  • mac上面使用zip命令压缩一劳永逸
  • 逆周期中的“深潜者”样本,解码康佳“智造”破局密码
  • Spark-SQL(二)
  • 轻量级Python IDE使用(五)——条件分支
  • STM32F103_HAL库+寄存器学习笔记15 - 梳理CAN发送失败时,涉及哪些寄存器
  • Linux:Ext系列文件系统
  • Python网络爬虫设计(一)
  • 牛客月赛114
  • DDS函数信号发生器设计
  • Redis之RedLock算法以及底层原理
  • YOLOv2学习笔记
  • 实战指南:封装Whisper为FastAPI接口并实现高并发处理-附整合包
  • 案例驱动的 IT 团队管理:创新与突破之路:第四章 危机应对:从风险预见到创新破局-4.2 人才流失危机-4.2.3梯队建设的“洋葱模型“
  • 【MySQL】
  • 阿里FPGA XCKU3P开箱- 25G 光纤
  • 花3000元就能买“国际机构”的证书?揭秘假证产业链
  • 南部战区回应菲护卫艇非法侵入中国黄岩岛领海:依法警告驱离
  • 南方将迎三轮降雨,两广旱区的“解渴雨”也要来了
  • 对话|棋后居文君:创造历史之后,还有继续追梦的心
  • 科普|一名肿瘤医生眼中的肺癌诊疗变化:从谈癌色变到与癌共存
  • 上海印发《新时代新征程促进民营经济高质量发展的若干措施》(全文)