扰码就是作有规律的随机化处理后的信码。作为现代通信的关键技术之一,扰码是为了提高传输数据的定时恢复能力和保密性而在比特层对需要传输的数据进行随机化处理的技术。这与扰码为什么有利于定时恢复与保密性的功能,首先保密性是因为解密方不知道扰码的生成多项式会给破译带来困难;定时恢复是因为扰码会消除连续的0与1,这有利于时钟的恢复。
扰码在通信系统中的位置如下:
扰码的优点如下:
(1) 在基带的输入端通常需要原始信号进行扰码处理;
(2) 扰码将输入进行随机化处理,消除连续的 0 或者 1, 可较少码间干扰和抖动;
(3) 扰码有加密的作用;
(4) 扰码能改善定时恢复的质量, 与此同时, 扰码能使信号频谱弥散而保持稳恒, 将数字信号的功率频谱扩展, 实现能量的分散
扰码的实现特别简单,我们只需要先生成相应的扰码序列,然后将扰码序列与输入序列进行异或运算,生成的序列就是扰码之后的序列。于是,现在我们便可以把焦点放到扰码序列的生成。扰码序列的生成需要生成多项式和寄存器的初值,这里生成多项式的概念不多加赘述,如果不了解的同学可以学习通信原理与信息论,书本上的知识比我写的好太多。
这里以经典的例子为例进行讲解,扰码序列的生成多项式为 1 + X 14 + X 15 1+X^{14}+X^{15} 1+X14+X15,初始序列为 100101010000000。这里稍微熟悉通信知识的可以知道这里的+其实就是异或运算。根据上面的生成多项式,扰码实现结构如下:
相信将上面的结构框图给出,大家写FPGA代码要比写MATLAB代码容易的多,因为FPGA本身特别适合描述这种结构。但是为了结构的完整性,我们将先进性MATLAB代码仿真,然后进行FPGA仿真,最后将两个仿真结果对比,从而验证我们实验的正确性。
从上面的介绍,相信大家可以明白扰码的生成分为两个步骤:
1、生成扰码序列
2、将扰码序列与输入序列进行相应的异或运算
这里不多说废话直接给出相应的代码,大家结合上面的原理介绍,相信可以看懂下面的代码,并且对扰码的生成会有更加深刻的认识。
clc;
clear all;
%------------------------------------------------------------------------------
% PLP-specific Parameters Definition
%------------------------------------------------------------------------------
K_BCH = 7032; % BCH unencoded block length
tx_nFrame = 1;
fid1 = fopen('scramble_data_in.txt','r');
DataIn = fscanf(fid1,'%d');
%------------------------------------------------------------------------------
% Procedure
%------------------------------------------------------------------------------
dataAux = DataIn;
% Get BB scrambling sequence
srBin = [1 0 0 1 0 1 0 1 0 0 0 0 0 0 0]; % Shift register content
bbPrbsBin = zeros(1,K_BCH); % Initialize output
% Generates PRBS sequence
for n=1:K_BCH
fedBackBit = xor(srBin(14), srBin(15)); % XOR bits 14 and 15
bbPrbsBin(n) = fedBackBit; % Output
srBin = [fedBackBit, srBin(1:14)];
end
bbPrbs = bbPrbsBin;
bbPrbs = bi2de(reshape(bbPrbs,8,[])','left-msb'); % convert to bytes
dataAux = bi2de(reshape(dataAux,8,[])','left-msb');
dataAux = reshape(dataAux, K_BCH/8, []); % One column per BBFrame
for bbFrameIdx = 1:size(dataAux,2)
dataAux(:,bbFrameIdx) = bitxor(dataAux(:,bbFrameIdx), bbPrbs);
end
data_lab = de2bi(dataAux, 8, 'left-msb');
data_lab = reshape(data_lab.', [], 1);
下面对上面的代码进行简要的介绍:
生成相应的输入序列,每7032个数据作为一个生成扰码的独立的块,即,连续的7032个数据序列之后,扰码序列就需要进行初始化操作。
上面的代码是生成扰码序列。
上面的代码是为了加快MATLAB的仿真速度,先将上面的扰码序列和输入序列每8位转换成十进制,然后分别对生成的十进制数进行异或运算,这可以加快MATLAB的速度。至于为什么,博主也不清楚,当然这也不是重点,不进行相应的转换,直接对二进制进行异或运算,这是完全正确的。
上面已经把原理介绍的比较清楚,这里直接给出相应的FPGA代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : tx_scramble.v
// Create Time : 2020-05-22 15:29:47
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tx_scramble
(
input sclk ,
input rst_n ,
input s_data_tvalid ,
input s_data_tdata ,
output reg s_data_tready ,
input s_data_tlast ,
output reg m_data_tvalid ,
output reg m_data_tdata ,
input m_data_tready ,
output reg m_data_tlast
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg s_data_tvalid_reg ;
reg s_data_tdata_reg ;
reg s_data_tlast_reg ;
reg [14:0] Init_cram_Sequ ;
reg data_ordy ;
wire start_data_invld ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign start_data_invld = ~s_data_tvalid_reg && s_data_tvalid;
always@(posedge sclk)
begin
s_data_tvalid_reg <= s_data_tvalid;
s_data_tdata_reg <= s_data_tdata;
s_data_tlast_reg <= s_data_tlast;
end
always@(posedge sclk)
if(~rst_n)
Init_cram_Sequ[14:0] <= 15'b000_0000_101010_01;
else if(s_data_tvalid)begin
Init_cram_Sequ[0] <= Init_cram_Sequ[14] ^ Init_cram_Sequ[13];
Init_cram_Sequ[14:1] <= Init_cram_Sequ[13:0];
end else
Init_cram_Sequ[14:0] <= 15'b000_0000_101010_01;
always@(posedge sclk)
if(s_data_tvalid_reg)
m_data_tdata <= Init_cram_Sequ[0]^s_data_tdata_reg;
else
m_data_tdata <= 0;
always@(posedge sclk)
begin
m_data_tvalid <= s_data_tvalid_reg;
m_data_tlast <= s_data_tlast_reg;
end
always@(posedge sclk)
if(~rst_n)
data_ordy <= 1;
else if(start_data_invld)
data_ordy <= 0;
else if(m_data_tlast)
data_ordy <= 1;
always@(posedge sclk)
s_data_tready <= data_ordy && m_data_tready;
endmodule
该代码是符合AXI-Stream协议,可以很容易进行与上下级的级联,也可以封装成容易使用的模块。
如果只给出扰码的源码,不给出相应的测试代码,大家不方便学习,所以这里我们给出相应的测试代码供大家学习。
tb_tx_scrable模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : tb_tx_scrable.v
// Create Time : 2020-05-22 15:56:09
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tb_tx_scrable;
parameter N = 2 ;
reg sclk ;
reg rst_n ;//
reg s_data_tdata ;//
wire s_data_tready ;
reg s_data_tlast ;
wire m_data_tvalid ;
wire m_data_tdata ;//
reg m_data_tready ;
wire m_data_tlast ;
wire event_status_missing ;//
reg s_data_tvalid_delay ;
reg s_data_tvalid ;//
integer file ;
integer i=0 ;
reg [15:0] cnt = 16'd0 ;
reg test[0:7032*N-1] ;
// sclk rst_n Gen
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
m_data_tready <= 1'b1;
#1000;
rst_n <= 1'b1;
end
always #10 sclk = ~sclk;
initial begin
s_data_tvalid <= 1'b0;
#2000;
repeat(10) @(posedge sclk);
s_data_tvalid <= 1'b1;
repeat(7032) @(posedge sclk);
s_data_tvalid <= 1'b0;
repeat(10) @(posedge sclk);
s_data_tvalid <= 1'b1;
repeat(7032) @(posedge sclk);
s_data_tvalid <= 1'b0;
end
initial begin
s_data_tlast <= 1'b0;
#2000;
repeat(7042) @(posedge sclk);
s_data_tlast <= 1'b1;
repeat(1) @(posedge sclk);
s_data_tlast <= 1'b0;
repeat(7041) @(posedge sclk);
s_data_tlast <= 1'b1;
repeat(1) @(posedge sclk);
s_data_tlast <= 1'b0;
end
always @(posedge sclk)
if(s_data_tvalid != 1'b1)
cnt <= 16'd0;
else
cnt <= cnt + 1'b1;
initial begin
$readmemb("scramble_data_in.txt",test);
end
always @(posedge sclk)
if(s_data_tvalid)
i<= i+1;
else
i<= i;
always@(posedge sclk)
begin
s_data_tdata <= test[i];
end
//output
initial
begin
#0;
file = $fopen("ms_scramble_out.txt","w+");
forever @(posedge sclk)
if(m_data_tvalid)
begin
$fdisplay(file,"%b",m_data_tdata);//
end
$fclose(file);
#100;
$stop;
end
always@(posedge sclk)
begin
s_data_tvalid_delay <= s_data_tvalid;
end
tx_scramble tx_scramble_inst(
.sclk (sclk ),
.rst_n (rst_n ),//
.s_data_tvalid (s_data_tvalid_delay ),//
.s_data_tdata (s_data_tdata ),//
.s_data_tready (s_data_tready ),
.s_data_tlast (s_data_tlast ),
.m_data_tvalid (m_data_tvalid ),
.m_data_tdata (m_data_tdata ),//
.m_data_tready (m_data_tready ),
.m_data_tlast (m_data_tlast )
);
//
endmodule
上面测试模块的写法非常经典,使用了将数据从txt文件读出与写入txt文件的方法,很值得大家学习,一定要试着学习这种方法。
我们利用Modelsim进行上面的仿真,可以得到下图:
然后将上面的数据与MATLAB生成的数据进行对比:
从上面可以看出我们Modelsim的仿真结果与MATLAB完全相同,从而验证了实验的正确性。从上面我们就已经成功将扰码的知识学会并利用的MATLAB与Modelsim交叉仿真验证。
[1]、电子发烧友学院
创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群: