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