Lesson 9

🎲 电子骰子

🏆 LFSR随机数1-6
✅ Verilator仿真验证通过

📖 实验描述

实现电子骰子,使用LFSR生成伪随机数,按键掷骰产生1-6的随机结果。

电子骰子是LFSR(线性反馈移位寄存器)的经典应用。 LFSR通过异或反馈产生伪随机序列。8位LFSR使用特定抽头位置(如8,6,5,4)可产生最长周期255的序列。 掷骰流程:按键触发时,捕获LFSR当前值,对6取模+1得到1-6的结果。 LFSR不停运行(高速循环),按键时刻的值看似随机。这虽然不是真随机,但对骰子应用足够。 电子骰子是理解伪随机数生成的入门项目。

🧠 核心概念

📐 电路结构

电路与状态图
电子骰子结构:

  clk → ┌──────────┐
         │  8-bit   │──→ 当前值 ──→ mod6 + 1 → result
         │  LFSR    │
         └──────────┘
              ↑
         feedback = bit8 ^ bit6 ^ bit5 ^ bit4

  roll按键 → 捕获LFSR值 → 显示结果

📝 设计步骤

  1. 1设计8位LFSR(反馈多项式x^8+x^6+x^5+x^4+1)
  2. 2确保LFSR持续高速运行
  3. 3实现按键消抖和边沿检测
  4. 4roll信号捕获LFSR当前值
  5. 58位值取模6加1映射到1-6
  6. 6防种子问题:LFSR初始值非零

💻 Verilog实现

dice.svSystemVerilog · Verilator 5.020
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
// Electronic Dice - 电子骰子
// 8-bit LFSR伪随机数, 按键掷骰1-6
module dice(
    input  wire       clk,     // 50MHz
    input  wire       rst,
    input  wire       roll,    // 掷骰按键
    output reg  [2:0] face,    // 骰子面值 1-6
    output reg        rolling  // 掷骰中
);

// 8-bit LFSR, feedback polynomial: x^8 + x^6 + x^5 + x^4 + 1
reg [7:0] lfsr;
wire feedback;

assign feedback = lfsr[7] ^ lfsr[5] ^ lfsr[4] ^ lfsr[3];

// LFSR runs continuously
always @(posedge clk or posedge rst) begin
    if (rst) begin
        lfsr <= 8'hAC;  // Non-zero seed
    end else begin
        lfsr <= {lfsr[6:0], feedback};
    end
end

// Roll debounce and edge detection
reg roll_d1, roll_d2, roll_d3;
wire roll_edge = roll_d2 && !roll_d3;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        roll_d1 <= 1'b0;
        roll_d2 <= 1'b0;
        roll_d3 <= 1'b0;
    end else begin
        roll_d1 <= roll;
        roll_d2 <= roll_d1;
        roll_d3 <= roll_d2;
    end
end

// Roll duration counter
reg [3:0] roll_cnt;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        face    <= 3'd1;
        rolling <= 1'b0;
        roll_cnt <= 4'd0;
    end else begin
        if (roll_edge && !rolling) begin
            rolling  <= 1'b1;
            roll_cnt <= 4'd10;  // Roll for 10 cycles
        end

        if (rolling) begin
            // Map LFSR to 1-6 during rolling
            face <= (lfsr[2:0] % 3'd6) + 3'd1;
            if (roll_cnt > 4'd0) begin
                roll_cnt <= roll_cnt - 4'd1;
            end else begin
                rolling <= 1'b0;
                // Final result
                face <= (lfsr % 6) + 1;
            end
        end
    end
end

endmodule

🔬 仿真说明

仿真环境与策略

测试:复位后面值=1;按roll键→rolling=1,面值快速变化;rolling结束后面值为1-6之间的稳定值。多次掷骰验证均匀性。

✅ 验证结果

Verilator 5.020 仿真通过

本实验所有Verilog代码已通过Verilator编译验证,功能行为正确。测试用例覆盖核心功能路径,确保设计满足规格要求。

⚠️ 常见错误

🌍 真实世界

工业应用

LFSR广泛应用于密码学、误码率测试、跳频通信等领域。FPGA上电初始化常用LFSR生成伪随机配置数据。真正的安全应用需要密码学安全的PRNG(如AES-CTR),而非简单LFSR。

💡 扩展挑战

🚀 自己动手

# 编译并运行
verilator --cc dice.sv --exe dice_tb.cpp --build -j 0
./obj_dir/Vdice

🎯 试一试

修改参数

尝试修改代码中的关键参数,观察仿真结果变化:

  • 调整位宽,观察不同数据范围
  • 修改初始值/种子,观察不同起始条件
  • 改变时钟分频,测试不同速度

💡 Verilator会在位宽不匹配时给出Warning,这是学习的好机会

添加功能

在现有基础上增加新功能:

  • 添加新的输入信号和控制逻辑
  • 增加状态或修改状态转移条件
  • 扩展输出,增加更多显示信息

🔧 增量开发:每次只改一个地方,验证通过后再改下一个

📋 Verilog速查

语法说明示例
reg [7:0]8位寄存器reg [7:0] data;
wire组合逻辑连线wire valid = cnt > 5;
always @(posedge clk)时序逻辑上升沿触发
always @(*)组合逻辑敏感列表自动推导
localparam局部常量localparam DIV = 50000000;
case多分支选择注意default分支
$display仿真打印不可综合,仅仿真用

📊 性能指标

资源估算(FPGA参考)

本设计在典型FPGA上的资源占用估算:LUT约20-120个,FF约30-100个,无BRAM/DSP依赖(特殊模块除外)。时钟频率可达50-100MHz+。Verilator仿真速度约5-10M周期/秒。

← 上一课 📚 目录 下一课 →