Verilog---扰码器/解扰器
扰码器
-
扰码器基于LFSR(线性移位计数器)实现,将输入数据转换为对应的伪随机数据;
-
LFSR(线性移位计数器)将输入数据与内部的寄存器数据反馈异或得到新的寄存器数据输出。
扰码器的优点
-
基于LFSR,逻辑实现简单,速度快;
-
可使数据团频谱展宽,减小EMI(电磁干扰)噪声;
-
可应用于密码系统、以太网等。
解扰器
- 由于异或运算的特性:
A ^ B = C,那么 B ^ C = A
,只需要将扰码器输出数据与相同的LFSR数据进行异或,即可得到原始数据。 可以很简单地实现对扰码数据的解扰。
扰码器/解扰器的实现
使用LFSR完成了扰码器/解扰器模块设计, 并进行扰码、解扰仿真操作。
scrambler模块输入变量包括:
-
reset_reg,内部LFSR寄存器复位标志。开始一次扰码->解码操作,扰码器和解码器可以各自进行一次寄存器复位操作(对同步没有要求,因为寄存器复位后,在有效输入数据到来之前LFSR没有更新)
-
flag_in, 输入数据有效标志, flag_in为高电平时才对输入数据进行扰码操作;
-
data_in, 输入数据,与flag_in同步输入
-
flag_out,输出数据有效标志;
-
data_out,输出数据,与flag_out同步输出。
该模块可以做为扰码器,也可以直接作为解扰器使用。
scramber模块代码
//scramber.v
//扰码器/解码器
`timescale 1ns/1ps
module scrambler(
input clk50M ,
input rst_n ,
input reset_reg ,//寄存器复位
input flag_in ,//输入数据有效标志
input [7:0] data_in ,//输入数据
output reg flag_out ,//输出数据有效标志
output reg [7:0] data_out //输出数据
);
localparam REG_INIT = 8'haa;
reg flag_in_r ;
reg [7:0] data_in_r ;
reg [7:0] lfsr ;
wire [7:0] lfsr_nxt ;
//data_in_r
always @(posedge clk50M) begin
flag_in_r <= flag_in;
data_in_r <= data_in;
end
//lfsr_nxt
assign lfsr_nxt[7] = lfsr[6];
assign lfsr_nxt[6] = lfsr[5];
assign lfsr_nxt[5] = lfsr[4];
assign lfsr_nxt[4] = lfsr[3];
assign lfsr_nxt[3] = lfsr[2];
assign lfsr_nxt[2] = lfsr[1];
assign lfsr_nxt[1] = lfsr[0];
assign lfsr_nxt[0] = lfsr[7] ^ lfsr[5] ^ lfsr[4] ^ lfsr[3];
//lfsr
always @(posedge clk50M or negedge rst_n) begin
if(~rst_n)
lfsr <= REG_INIT;
else if(reset_reg)
lfsr <= REG_INIT;
else if(flag_in)
lfsr <= lfsr_nxt;
else
lfsr <= lfsr;
end
//data_out
always @(posedge clk50M or negedge rst_n) begin
if(~rst_n)
data_out <= 8'h00;
else
data_out = lfsr ^ data_in_r;
end
//flag_out
always @(posedge clk50M or negedge rst_n) begin
if(~rst_n)
flag_out <= 1'b0;
else if(flag_in_r)
flag_out <= 1'b1;
else
flag_out <= 1'b0;
end
endmodule
扰码器 -> 解扰器仿真代码
`timescale 1ns/1ps
module tb_scrambler();
reg clk50M ;
reg rst_n ;
reg reset_reg ;
reg flag_in ;
reg [7:0] data_in ;
wire flag_out ;
wire [7:0] data_out ;
//解扰数据输出
reg dis_clk50M ;
wire dis_flag_out;
wire dis_data_out;
//扰码器
scrambler scrambler_inst(
.clk50M (clk50M ),
.rst_n (rst_n ),
.reset_reg (reset_reg ),//寄存器复位
.flag_in (flag_in ),//输入数据有效标志
.data_in (data_in ),//输入数据
.flag_out (flag_out ),//输出数据有效标志
.data_out (data_out ) //输出数据
);
//解扰器
scrambler dis_scrambler_inst(
.clk50M (dis_clk50M ),
.rst_n (rst_n ),
.reset_reg (reset_reg ),
.flag_in (flag_out ),
.data_in (data_out ),
.flag_out (dis_flag_out ),
.data_out (dis_data_out )
);
//clk50M,扰码器时钟
initial begin
clk50M = 1'b1;
end
always #10 clk50M = ~clk50M;
//dis_clk50M,解扰器时钟
initial begin
dis_clk50M = 1'b1;
#1.5;
forever begin
dis_clk50M = ~dis_clk50M;
#10;
end
end
initial begin
rst_n = 1'b0;
reset_reg = 1'b0;
flag_in = 1'b0;
data_in = 8'h00;
#100;
rst_n = 1'b1;
#10;
input_data(8'h88, 10);
#65;
input_data(8'ha5, 10);
end
//输入数据,指定起始值以及数据个数
//tb1_data_in
task input_data(
input [7:0] start_data, //起始数据
input [8:0] num //数据个数
);
reg [8:0] i;
begin
flag_in = 1'b1;
for(i = 0; i < num; i = i + 1) begin
data_in = start_data + i;
#20;
end
flag_in = 1'b0;
end
endtask
endmodule