博文目錄
- 寫在前面
- 正文
-
- 原理
- Verilog實作
- 仿真測試
- 代碼提示
- 參考資料
- 交個朋友
相關博文
部落格首頁
注:學習交流使用!
線性回報移位寄存器(LFSR)的英文全稱為:Linear Feedback Shift Register。
賽靈思公司的高速序列槽IP核示例程式經常以LFSR為例,例如Aurora IP的例子程式:
//______________________________ Transmit Data __________________________________
//Transmit data when TX_DST_RDY_N is asserted.
//Random data is generated using XNOR feedback LFSR
//TX_SRC_RDY_N is asserted on every cycle with data
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hABCD; //random seed value
TX_SRC_RDY_N <= `DLY 1'b1;
end
else if(!TX_DST_RDY_N)
begin
data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},
data_lfsr_r[0:14]};
TX_SRC_RDY_N <= `DLY 1'b0;
end
//Connect TX_D to the DATA LFSR register
assign TX_D = {1{data_lfsr_r}};
相關部落格連結
LFSR代表線性回報移位寄存器,它是一種在FPGA内部有用的設計。 LFSR易于合成,這意味着它們占用的資源相對較少,并且可以在FPGA内部以很高的時鐘速率運作。 使用LFSR可以使許多應用受益,包括:
- 計數器(Counters)
- 測試碼型發生器(Test Pattern Generators)
- 資料加擾(Data Scrambling)
- 密碼學(Cryptography)
線性回報移位寄存器實作為FPGA内部的一系列觸發器,這些觸發器連接配接在一起作為移位寄存器。 移位寄存器鍊的多個抽頭用作XOR或XNOR門的輸入。 然後,此門的輸出用作對移位寄存器鍊開始的回報,是以用作LFSR中的回報。
例如5bit的LFSR的一種形式:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SOjhzMlZWN1kDZwAjNzMjY3QzNyMjM5YmM1ImN3U2Mj9CXwIzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL4M3Lc9CX6MHc0RHaiojIsJye.png)
運作LFSR時,由各個觸發器生成的模式是僞随機的,這意味着它接近随機。 它不是完全随機的,因為從LFSR模式的任何狀态,您都可以預測下一個狀态。 有一些重要的移位寄存器屬性需要注意:
- LFSR模式是僞随機的。
-
輸出模式是确定性的。 您可以通過了解XOR門的位置以及目前模式來确定下一個狀态。
當抽頭使用XOR門時,全0的模式不會出現。 由于0與0異或将始終産生0,是以LFSR将停止運作。
- 當抽頭使用XNOR門時,全1的模式将不會出現。 由于将1與1進行異或運算将始終産生1,是以LFSR将停止運作。
- 任何LFSR的最大可能疊代次數= 2^Bits-1
更長的LFSR将花費更長的時間來運作所有疊代。 N位LFSR的最大可能疊代次數為2^N-1。
如果您考慮一下,所有N位長的東西的所有可能模式都是2^N。 是以,隻有一種模式無法使用LFSR表示。 當使用XOR門時,該模式全為0,而使用XNOR門作為您的回報門時全為1。
VHDL和Verilog代碼建立所需的任何N位寬的LFSR。 它使用多項式(這是LFSR背後的數學方法)為每個位寬建立最大可能的LFSR長度。
是以,對于3位,需要2^3-1 = 7個時鐘來運作所有可能的組合;
對于4位:2^4-1 = 15;
對于5位:2^5-1 = 31,依此類推。
我基于XNOR實作 以允許FPGA在LFSR上以全零狀态啟動。 這是Xilinx釋出的所有LFSR模式的完整表。
下面給出Verilog實作代碼:
`timescale 1ns / 1ps
//
// Company:
// Engineer: Reborn Lee
// Create Date: 2020/06/01 12:50:38
// Design Name:
// Module Name: lfsr
// Revision 0.01 - File Created
// Additional Comments:
//
//
module lfsr #(parameter NUM_BITS = 3)(
input i_Clk,
input i_Enable,
// data valid
input i_Seed_DV,
// Optional Seed Value
input [NUM_BITS-1:0] i_Seed_Data,
output [NUM_BITS-1:0] o_LFSR_Data,
output o_LFSR_Done
);
// internal variables
reg [NUM_BITS:1] r_LFSR = 0;
reg r_XNOR;
// Purpose: Load up LFSR with Seed if Data Valid (DV) pulse is detected.
// Othewise just run LFSR when enabled.
always @(posedge i_Clk)
begin
if (i_Enable == 1'b1)
begin
if (i_Seed_DV == 1'b1)
r_LFSR <= i_Seed_Data;
else
r_LFSR <= {r_LFSR[NUM_BITS-1:1],r_XNOR}; //left right
end
end
// Create Feedback Polynomials. Based on Application Note:
// http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
always @(*)
begin
case (NUM_BITS)
3: begin
r_XNOR = r_LFSR[3] ^~ r_LFSR[2];
end
4: begin
r_XNOR = r_LFSR[4] ^~ r_LFSR[3];
end
5: begin
r_XNOR = r_LFSR[5] ^~ r_LFSR[3];
end
6: begin
r_XNOR = r_LFSR[6] ^~ r_LFSR[5];
end
7: begin
r_XNOR = r_LFSR[7] ^~ r_LFSR[6];
end
8: begin
r_XNOR = r_LFSR[8] ^~ r_LFSR[6] ^~ r_LFSR[5] ^~ r_LFSR[4];
end
9: begin
r_XNOR = r_LFSR[9] ^~ r_LFSR[5];
end
10: begin
r_XNOR = r_LFSR[10] ^~ r_LFSR[7];
end
11: begin
r_XNOR = r_LFSR[11] ^~ r_LFSR[9];
end
12: begin
r_XNOR = r_LFSR[12] ^~ r_LFSR[6] ^~ r_LFSR[4] ^~ r_LFSR[1];
end
13: begin
r_XNOR = r_LFSR[13] ^~ r_LFSR[4] ^~ r_LFSR[3] ^~ r_LFSR[1];
end
14: begin
r_XNOR = r_LFSR[14] ^~ r_LFSR[5] ^~ r_LFSR[3] ^~ r_LFSR[1];
end
15: begin
r_XNOR = r_LFSR[15] ^~ r_LFSR[14];
end
16: begin
r_XNOR = r_LFSR[16] ^~ r_LFSR[15] ^~ r_LFSR[13] ^~ r_LFSR[4];
end
17: begin
r_XNOR = r_LFSR[17] ^~ r_LFSR[14];
end
18: begin
r_XNOR = r_LFSR[18] ^~ r_LFSR[11];
end
19: begin
r_XNOR = r_LFSR[19] ^~ r_LFSR[6] ^~ r_LFSR[2] ^~ r_LFSR[1];
end
20: begin
r_XNOR = r_LFSR[20] ^~ r_LFSR[17];
end
21: begin
r_XNOR = r_LFSR[21] ^~ r_LFSR[19];
end
22: begin
r_XNOR = r_LFSR[22] ^~ r_LFSR[21];
end
23: begin
r_XNOR = r_LFSR[23] ^~ r_LFSR[18];
end
24: begin
r_XNOR = r_LFSR[24] ^~ r_LFSR[23] ^~ r_LFSR[22] ^~ r_LFSR[17];
end
25: begin
r_XNOR = r_LFSR[25] ^~ r_LFSR[22];
end
26: begin
r_XNOR = r_LFSR[26] ^~ r_LFSR[6] ^~ r_LFSR[2] ^~ r_LFSR[1];
end
27: begin
r_XNOR = r_LFSR[27] ^~ r_LFSR[5] ^~ r_LFSR[2] ^~ r_LFSR[1];
end
28: begin
r_XNOR = r_LFSR[28] ^~ r_LFSR[25];
end
29: begin
r_XNOR = r_LFSR[29] ^~ r_LFSR[27];
end
30: begin
r_XNOR = r_LFSR[30] ^~ r_LFSR[6] ^~ r_LFSR[4] ^~ r_LFSR[1];
end
31: begin
r_XNOR = r_LFSR[31] ^~ r_LFSR[28];
end
32: begin
r_XNOR = r_LFSR[32] ^~ r_LFSR[22] ^~ r_LFSR[2] ^~ r_LFSR[1];
end
endcase // case (NUM_BITS)
end // always @ (*)
assign o_LFSR_Data = r_LFSR[NUM_BITS:1];
// Conditional Assignment (?)
assign o_LFSR_Done = (r_LFSR[NUM_BITS:1] == i_Seed_Data) ? 1'b1 : 1'b0;
endmodule
給出一個簡單的仿真測試:
`timescale 1ns / 1ps
module lfsr_tb ();
parameter c_NUM_BITS = 4;
reg r_Clk = 1'b0;
wire [c_NUM_BITS-1:0] w_LFSR_Data;
wire w_LFSR_Done;
lfsr #(.NUM_BITS(c_NUM_BITS)) LFSR_inst
(.i_Clk(r_Clk),
.i_Enable(1'b1),
.i_Seed_DV(1'b0),
.i_Seed_Data({c_NUM_BITS{1'b0}}), // Replication
.o_LFSR_Data(w_LFSR_Data),
.o_LFSR_Done(w_LFSR_Done)
);
always @(*)
#10 r_Clk <= ~r_Clk;
endmodule // LFSR_TB
仿真結果:
值得注意的是r_LFSR的定義,内部位從1到NUM_BITS,而非0到NUM_BITS -1;
reg [NUM_BITS:1] r_LFSR = 0;
這就意味着移位代碼這樣寫:
r_LFSR <= {r_LFSR[NUM_BITS-1:1],r_XNOR}; //left right
也就是低位往高位移,也即左移。
這是根據這張圖來的:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SOjhzMlZWN1kDZwAjNzMjY3QzNyMjM5YmM1ImN3U2Mj9CXwIzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL4M3Lc9CX6MHc0RHaiojIsJye.png)
至于仿真檔案中對仿真輸入設計的也十分簡單,就是單純讓種子為0,也即初始值為0,之後進行回報移位操作。
lfsr #(.NUM_BITS(c_NUM_BITS)) LFSR_inst
(.i_Clk(r_Clk),
.i_Enable(1'b1),
.i_Seed_DV(1'b0),
.i_Seed_Data({c_NUM_BITS{1'b0}}), // Replication
.o_LFSR_Data(w_LFSR_Data),
.o_LFSR_Done(w_LFSR_Done)
);
在設計檔案内部,r_LFSR初始值就是為0,是以,不給種子也可以,反正i_Seed_DV本身在測試檔案中就無效。
關于回報多項式是如何确定的呢?
正是上面提供的文檔:
抽頭确定
此表列出了最大長度為168位的LFSR計數器的相應抽頭。前40位的基本描述和表最初在XCELL中釋出,并在1993年和1994年Xilinx資料手冊的第9-24頁上重印。
- n位LFSR計數器的最大序列長度可以是2^n-1。在這種情況下,它會經曆所有可能的代碼排列,除了一個鎖定狀态。
- 最大長度的n位LFSR計數器由一個n位移位寄存器組成,該移位寄存器在從最後輸出Qn到第一輸入D1的回報路徑中具有XNOR。XNOR将鎖定狀态設為all-one狀态,也就是說如果種子為全1,則LFSR将鎖定,其最終移位結果永遠為1;XOR将鎖定狀态設為all-zeros狀态。
- 對于普通的Xilinx應用程式,全1的觸發器都更容易避免,因為“預設情況下”觸發器在全零狀态下喚醒。
- Table3描述了必須用作XNOR輸入的輸出。LFSR輸出通常标記為1到n,1是移位寄存器的第一級,n是最後一級。這與二進制計數器的傳統0到(n-1)表示法不同。多輸入XNOR也稱為均勻奇偶校驗電路。
- 請注意,此表中描述的連接配接不一定唯一;某些其他連接配接也可能導緻最大長度序列。