:实现4路LED不同频率独立闪烁)
FPGA入门文章目录FPGA入门前言一、整体设计思路二、完整代码2.1 底层单路LED闪烁模块 led_twinkle.v2.2 顶层4路不同频率闪烁模块led_twinkle_4.v三、频率与参数的关系四、重点精讲Verilog两种Parameter参数修改方式4.1 实例化 # 直接传参最好4.2 defparam 后置重定义old school五、工程核心知识点总结前言本篇博文基于Verilog HDL 实现4路LED不同频率独立闪烁工程。核心不只是实现LED闪烁效果更重点讲解Verilog中模块Parameter参数的两种修改方式是FPGA模块化设计、代码复用的核心基础知识点超级适合新手入门学习。一、整体设计思路本工程采用底层通用模块顶层调用模块的分层设计思想底层基础模块 led_twinkle设计一个可配置参数的单路LED闪烁模块通过参数 MCNT 控制闪烁频率预留参数修改接口支持代码复用。顶层模块 led_twinkle_44次例化底层闪烁模块通过两种不同的参数修改方式给4个实例配置不同的计数最大值最终实现4路LED不同频率独立闪烁。二、完整代码2.1 底层单路LED闪烁模块 led_twinkle.v带默认参数的通用闪烁模块可单独使用也可被顶层模块复用。moduleled_twinkle(Clk,Reset_n,Led);input Clk;input Reset_n;output reg Led;reg[24:0]counter;// 默认计数最大值可通过顶层修改parameter MCNT25000000-1;// 计数器循环计数逻辑always(posedge Clk or negedge Reset_n)if(!Reset_n)counter0;elseif(counterMCNT)counter0;elsecountercounter1d1;// 计数溢出LED电平翻转实现闪烁always(posedge Clk or negedge Reset_n)if(!Reset_n)Led1b0;elseif(counterMCNT)Led!Led;endmodule2.2 顶层4路不同频率闪烁模块led_twinkle_4.v多次例化底层模块搭配两种参数配置方式实现差异化频率控制。moduleled_twinkle_4(Clk,Reset_n,Led);input Clk;input Reset_n;output[3:0]Led;// 定义4组不同的计数阈值对应4种闪烁频率parameter MCNT025000000-1;// 最慢parameter MCNT112500000-1;parameter MCNT26250000-1;parameter MCNT32500000-1;// 最快// 方式1defparam 后置参数重定义led_twinkleled_twinkle_inst0(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[0]));defparam led_twinkle_inst0.MCNTMCNT0;// 方式2实例化时 # 直接传参官方推荐写法led_twinkle #(.MCNT(MCNT1))led_twinkle_inst1(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[1]));// 方式1defparam 后置参数重定义led_twinkleled_twinkle_inst2(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[2]));defparam led_twinkle_inst2.MCNTMCNT2;// 方式1defparam 后置参数重定义led_twinkleled_twinkle_inst3(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[3]));defparam led_twinkle_inst3.MCNTMCNT3;endmodule三、频率与参数的关系本工程基于50MHz 系统时钟时钟周期20ns核心逻辑计数器从0计数到MCNT时清零同时翻转LED电平MCNT数值越大计数耗时越长LED闪烁频率越慢。4路LED频率对应关系Led[0]MCNT25000000-1 → 翻转周期0.5s → 闪烁周期1s最慢Led[1]MCNT12500000-1 → 翻转周期0.25s → 闪烁周期0.5sLed[2]MCNT6250000-1 → 翻转周期0.125s → 闪烁周期0.25sLed[3]MCNT2500000-1 → 翻转周期0.05s → 闪烁周期0.1s最快四、重点精讲Verilog两种Parameter参数修改方式这是本文核心干货工程中同时使用了Verilog仅有的两种模块参数重配置方法下面逐行拆解、对比优劣。4.1 实例化 # 直接传参最好led_twinkle #(.MCNT(MCNT1))led_twinkle_inst1(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[1]));逐步解析led_twinkle指定需要调用的底层基础模块。#()Verilog专属参数传递符号代表「本次例化需要重写模块参数」。.MCNT(MCNT1)左侧.MCNT底层模块定义的参数名必须完全一致右侧MCNT1顶层自定义的新参数值替换底层默认值。led_twinkle_inst1模块实例唯一名称用于区分多个复用模块。端口映射绑定时钟、复位、LED输出引脚。优点参数和实例绑定在一起代码可读性极高编译兼容性强是企业开发、项目开发的标准写法。4.2 defparam 后置重定义old school代码片段// 1. 先正常例化模块使用默认参数led_twinkleled_twinkle_inst0(.Clk(Clk),.Reset_n(Reset_n),.Led(Led[0]));// 2. 单独重定义参数defparam led_twinkle_inst0.MCNTMCNT0;逐步解析第一步正常例化创建模块实例此时模块暂时使用内部默认的MCNT参数。defparam关键字全称define parameter作用是强制重定义已实例化模块的参数。led_twinkle_inst0.MCNT精准定位参数位置——指定「某个实例的某个参数」。 MCNT0赋值新参数覆盖模块默认参数实现频率修改。缺点参数配置与模块例化代码分离可读性差部分新仿真工具兼容性一般仅用于兼容老旧项目。五、工程核心知识点总结模块化复用思想将通用功能LED闪烁封装为独立模块多次例化即可重复使用减少冗余代码。Parameter参数化核心parameter定义的模块参数默认值可被顶层覆盖实现一个模块、多种功能。频率控制逻辑计数器阈值MCNT与闪烁频率成反比数值越小闪烁速度越快。独立实例特性4个模块实例完全独立参数互不影响因此4路LED可以实现不同频率独立闪烁。