2025年12月22日 星期一

LFSR (Linear Feedback Shift Registers)

 LFSR (Linear Feedback Shift Registers)




Galois LFSR 在硬體實作中更受歡迎,主要是因為它的異或門(XOR gate)是並聯位在暫存器之間,電路延遲(Propagation Delay)較低,時鐘頻率可以跑得更高;而 Fibonacci 的 XOR 則是串聯在回授路徑上。

Galois vs Fibonacci LFSR 實作模擬

這個程式會顯示兩個 4-bit 的移位暫存器(多項式採用 x^4 + x^3 + 1),點擊按鈕後可以同步觀察兩者的位移與 XOR 運算的差異。


  • Galois LFSR (左側):

    • 原理:當輸出位元為 1 時,特定的 "Tap" 位元會在移位過程中與輸出值進行 XOR。

    • 視覺觀察:你會發現它的 XOR 運算是「由外往內」注入的。

  • Fibonacci LFSR (右側):

    • 原理:選定多個位元(Taps)進行 XOR 運算後,將結果回傳到第一個位元。

    • 視覺觀察:這是一般教科書最常教的方式,所有運算都在「回授路徑」上完成。




  • import tkinter as tk

    from tkinter import ttk


    class LFSRVisualizer:

        def __init__(self, root):

            self.root = root

            self.root.title("LFSR 實作對比: Galois vs Fibonacci (x^4 + x^3 + 1)")

            

            # 初始狀態 (4-bit, 不能為全 0)

            self.galois_state = [1, 0, 0, 0]

            self.fibonacci_state = [1, 0, 0, 0]

            

            self.setup_ui()


        def setup_ui(self):

            # 使用主要容器

            main_frame = ttk.Frame(self.root, padding="20")

            main_frame.grid(row=0, column=0)


            # 標題與多項式說明

            title_label = ttk.Label(main_frame, text="多項式: x⁴ + x³ + 1", font=("Arial", 14, "bold"))

            title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))


            # --- 左側: Galois ---

            galois_frame = ttk.LabelFrame(main_frame, text=" Galois LFSR (內部異或) ", padding="10")

            galois_frame.grid(row=1, column=0, padx=15)

            

            # Galois 電路示意圖 (簡化文字版)

            self.g_diag = tk.Label(galois_frame, text="[IN] → [b0] → [b1] → [b2] → (XOR) → [b3] → [OUT]\n"

                                                      "             ↑______________|", 

                                   font=("Courier", 10), justify=tk.LEFT, bg="#f0f0f0")

            self.g_diag.pack(pady=5)

            

            self.galois_canvas = tk.Canvas(galois_frame, width=320, height=100, bg="white")

            self.galois_canvas.pack()


            # --- 右側: Fibonacci ---

            fib_frame = ttk.LabelFrame(main_frame, text=" Fibonacci LFSR (外部回授) ", padding="10")

            fib_frame.grid(row=1, column=1, padx=15)

            

            # Fibonacci 電路示意圖 (簡化文字版)

            self.f_diag = tk.Label(fib_frame, text="  ____________(XOR) <--- [b2] <--- [b3] [OUT]\n"

                                                   " ↓             |___________________|\n"

                                                   "[IN] → [b0] → [b1] → [b2] → [b3]", 

                                   font=("Courier", 10), justify=tk.LEFT, bg="#f0f0f0")

            self.f_diag.pack(pady=5)

            

            self.fib_canvas = tk.Canvas(fib_frame, width=320, height=100, bg="white")

            self.fib_canvas.pack()


            # --- 控制區 ---

            btn_frame = ttk.Frame(main_frame)

            btn_frame.grid(row=2, column=0, columnspan=2, pady=20)

            

            self.step_btn = ttk.Button(btn_frame, text=" 執行一個移位 (Step) ", command=self.step)

            self.step_btn.pack(side=tk.LEFT, padx=5)

            

            self.reset_btn = ttk.Button(btn_frame, text=" 重設 (Reset) ", command=self.reset)

            self.reset_btn.pack(side=tk.LEFT, padx=5)


            self.draw_registers()


        def draw_single_lfsr(self, canvas, state, highlight_idx=None):

            canvas.delete("all")

            for i in range(4):

                x0, y0 = 40 + (i * 60), 30

                x1, y1 = x0 + 45, 75

                

                # 繪製暫存器方框

                color = "#e1f5fe" if i != highlight_idx else "#fff9c4"

                canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline="black", width=2)

                

                # 數值

                canvas.create_text(x0 + 22, y0 + 22, text=str(state[i]), font=("Arial", 18, "bold"))

                

                # 索引

                canvas.create_text(x0 + 22, y0 - 10, text=f"b{i}", font=("Arial", 10))

                

                # 箭頭

                if i < 3:

                    canvas.create_line(x1, (y0+y1)/2, x1+15, (y0+y1)/2, arrow=tk.LAST)


        def draw_registers(self):

            self.draw_single_lfsr(self.galois_canvas, self.galois_state)

            self.draw_single_lfsr(self.fib_canvas, self.fib_state_visual())


        def fib_state_visual(self):

            return self.fibonacci_state


        def step(self):

            # 1. Galois Logic (x^4 + x^3 + 1)

            # 輸出位元是最後一格 (b3)

            out = self.galois_state[3]

            new_g = [0] * 4

            new_g[0] = out                 # b3 回授到 b0

            new_g[1] = self.galois_state[0] # 正常移位

            new_g[2] = self.galois_state[1] # 正常移位

            new_g[3] = self.galois_state[2] ^ out # Tap 在此:b2 XOR b3(out)

            self.galois_state = new_g


            # 2. Fibonacci Logic (x^4 + x^3 + 1)

            # Tap 在 b2(x^3) 與 b3(x^4)

            feedback = self.fibonacci_state[2] ^ self.fibonacci_state[3]

            new_f = [feedback] + self.fibonacci_state[:-1]

            self.fibonacci_state = new_f


            self.draw_registers()


        def reset(self):

            self.galois_state = [1, 0, 0, 0]

            self.fibonacci_state = [1, 0, 0, 0]

            self.draw_registers()


    if __name__ == "__main__":

        root = tk.Tk()

        app = LFSRVisualizer(root)

        root.mainloop()


    沒有留言:

    張貼留言

    WOKWI 模擬 MFRC522 RFID Reader + 5個 Tag 發行到MQTT 上

    WOKWI 模擬 MFRC522 RFID Reader + 5個 Tag  發行到MQTT 上 MQTTgo.io # MQTT 設定 MQTT_BROKER = "mqttgo.io" MQTT_PORT = 1883 MQTT_TOPIC = ...