)
让FPGA开发板重获新生用拨码开关和LED实现四位乘法器的趣味实验看着角落里积灰的FPGA开发板是不是总想找点有趣的项目练练手今天我们就来玩个既简单又有成就感的实验——用拨码开关和LED灯制作一个四位二进制乘法器。这个项目不仅能帮你理解Verilog硬件描述语言的精髓还能让你直观感受到代码如何控制真实硬件。1. 硬件准备与环境搭建1.1 所需材料清单FPGA开发板如Altera Cyclone系列4位拨码开关用于输入被乘数4个独立按键用于输入乘数8个LED灯用于显示乘积结果USB-Blaster下载器Quartus II开发环境推荐13.0以上版本提示大多数基础FPGA开发板都自带这些基础外设无需额外购买模块。1.2 Quartus II安装与配置安装Quartus II时建议选择以下组件Quartus II ProgrammerModelSim-Altera Starter Edition对应你FPGA芯片型号的器件支持包安装完成后需要设置环境变量确保USB-Blaster驱动正常工作。在Linux系统下可能需要手动配置udev规则# 创建规则文件 sudo nano /etc/udev/rules.d/51-usb-blaster.rules # 添加以下内容 SUBSYSTEMusb, ATTR{idVendor}09fb, ATTR{idProduct}6001, MODE0666 SUBSYSTEMusb, ATTR{idVendor}09fb, ATTR{idProduct}6002, MODE0666 SUBSYSTEMusb, ATTR{idVendor}09fb, ATTR{idProduct}6003, MODE06662. 乘法器原理与Verilog实现2.1 二进制乘法基础四位二进制乘法器的核心原理与我们熟悉的十进制乘法类似只是基数变成了2。例如1011 (11) × 1101 (13) -------- 1011 0000 1011 1011 -------- 10001111 (143)在硬件实现上我们采用移位相加的算法初始化结果为0从最低位开始检查乘数的每一位如果当前位为1将被乘数左移相应位数后加到结果中重复直到处理完所有位2.2 Verilog代码实现创建一个新的Verilog HDL文件File → New → Verilog HDL File输入以下代码module binary_multiplier( input [3:0] multiplicand, // 拨码开关输入的被乘数 input [3:0] multiplier, // 按键输入的乘数 output reg [7:0] product // LED显示的乘积 ); always (*) begin product 8b0; // 初始化乘积为0 // 移位相加算法 for (integer i 0; i 4; i i 1) begin if (multiplier[i]) begin product product (multiplicand i); end end end endmodule这段代码的关键点使用always (*)组合逻辑块确保输入变化时立即更新输出是Verilog的左移运算符for循环遍历乘数的每一位3. 引脚分配与硬件连接3.1 开发板外设映射不同开发板的引脚定义可能有所差异以下是一个典型示例信号引脚编号开发板对应外设multiplicand[0]PIN_34SW1multiplicand[1]PIN_33SW2multiplicand[2]PIN_32SW3multiplicand[3]PIN_31SW4multiplier[0]PIN_25KEY1multiplier[1]PIN_24KEY2multiplier[2]PIN_23KEY3multiplier[3]PIN_22KEY4product[0]PIN_100LED1product[1]PIN_99LED2.........在Quartus II中通过Assignment → Pin Planner进行引脚分配在Filter栏输入信号名在Location列选择对应引脚号保存分配并重新编译3.2 硬件连接检查在烧录程序前建议用万用表检查以下关键点所有开关/按键在按下时是否确实将引脚拉低/拉高LED阳极是否通过限流电阻连接到FPGA引脚共阳/共阴LED配置是否与程序逻辑匹配注意大多数开发板已经做好这些连接自制电路时需要特别注意。4. 功能验证与调试技巧4.1 基础测试用例验证乘法器功能时建议尝试以下测试组合测试案例被乘数 (二进制)乘数 (二进制)预期结果 (二进制)最大乘积1111 (15)1111 (15)11100001 (225)零测试0000 (0)任意值00000000 (0)单位测试0001 (1)0001 (1)00000001 (1)边界测试1000 (8)1000 (8)01000000 (64)4.2 ModelSim仿真在烧录到开发板前可以先进行仿真验证创建Testbench文件timescale 1ns/1ps module tb_multiplier; reg [3:0] a, b; wire [7:0] p; binary_multiplier uut (.multiplicand(a), .multiplier(b), .product(p)); initial begin // 测试案例1: 3 × 5 a 4b0011; b 4b0101; #10; // 测试案例2: 12 × 10 a 4b1100; b 4b1010; #10; // 更多测试案例... $stop; end endmodule在ModelSim中运行仿真观察波形图验证结果。4.3 常见问题排查遇到问题时可以检查以下几个方面LED不亮确认引脚分配正确检查LED极性共阳/共阴测量FPGA引脚是否有输出结果显示错误检查开关/按键是否接触不良确认没有信号被意外优化掉重新编译并确保所有修改已保存下载失败确认USB-Blaster驱动安装正确检查开发板供电是否正常尝试更换USB端口或电缆5. 进阶优化与扩展思路5.1 性能优化技巧基础版本完成后可以考虑以下优化流水线设计// 一级流水部分积计算 always (posedge clk) begin pp0 multiplier[0] ? multiplicand : 0; pp1 multiplier[1] ? (multiplicand 1) : 0; // ...其他部分积 end // 二级流水结果累加 always (posedge clk) begin product pp0 pp1 pp2 pp3; endBooth编码减少部分积数量提升效率Wallace树优化加法器结构减少关键路径延迟5.2 功能扩展建议添加BCD码转换用七段数码管显示十进制结果实现带符号数的乘法补码表示增加串行接口支持PC端输入测试用例设计可视化界面实时显示运算过程5.3 教学演示技巧为了更好展示乘法器工作原理可以放慢时钟频率用LED显示中间计算过程为每个部分积分配单独的LED组添加单步执行模式通过按键控制计算步骤// 单步执行控制示例 reg [1:0] step; always (posedge clk or posedge reset) begin if (reset) step 0; else if (step_btn) step step 1; end always (*) begin case (step) 0: product 0; 1: product multiplier[0] ? multiplicand : 0; // ...其他步骤 endcase end这个项目最吸引人的地方在于你能亲眼看到抽象的二进制运算如何转化为实实在在的灯光信号。当第一次拨动开关、按下按键看到LED灯正确显示出乘积时那种成就感是仿真软件无法比拟的。