校招Verilog——PWM呼吸灯
PWM呼吸灯,从51单片机开始玩的东西,在FPGA上再实现一次,见代码:
一、设计文件
1 //====================================================================== 2 // --- 名称 : breathing_led 3 // --- 作者 : xianyu_FPGA 4 // --- 日期 : 2018-12-15 5 // --- 描述 : PWM频率调制实现真呼吸灯的效果,4秒1次循环, 6 // 每2ms秒变化1次,前2秒亮度增大,后2秒亮度减小 7 //====================================================================== 8 9 module breathing_led 10 //---------------------<端口声明>--------------------------------------- 11 ( 12 input wire clk , //时钟,50Mhz 13 input wire rst_n , //复位,低电平有效 14 output wire led //led灯 15 ); 16 //---------------------<参数定义>--------------------------------------- 17 parameter TIME_2MS = 100_000 ; //2ms时间 18 parameter TIME_2MS_W = 17 ; //2ms时间位宽 19 parameter NUM = 1000 ; //2ms到2s为1000份 20 parameter NUM_W = 10 ; //份数位宽 21 parameter STEP = 100 ; //2ms也分成1000份,每份为步长100 22 23 //---------------------<信号定义>--------------------------------------- 24 reg [TIME_2MS_W-1:0] cnt0 ; 25 wire add_cnt0 ; 26 wire end_cnt0 ; 27 reg [NUM_W:0] cnt1 ; 28 wire add_cnt1 ; 29 wire end_cnt1 ; 30 reg [1:0] cnt2 ; 31 wire add_cnt2 ; 32 wire end_cnt2 ; 33 reg [TIME_2MS_W-1:0] pwm_high ; 34 35 //---------------------------------------------------------------------- 36 //-- 2ms时间计时 37 //---------------------------------------------------------------------- 38 always @(posedge clk or negedge rst_n)begin 39 if(!rst_n) 40 cnt0 <= 0; 41 else if(add_cnt0)begin 42 if(end_cnt0) 43 cnt0 <= 0; 44 else 45 cnt0 <= cnt0 + 1; 46 end 47 else 48 cnt0 <= cnt0; 49 end 50 51 assign add_cnt0 = 1; 52 assign end_cnt0 = add_cnt0 && cnt0==TIME_2MS-1 ; 53 54 //---------------------------------------------------------------------- 55 //-- 每2ms计1次,计到2秒共需计NUM次 56 //---------------------------------------------------------------------- 57 always @(posedge clk or negedge rst_n)begin 58 if(!rst_n) 59 cnt1 <= 0; 60 else if(add_cnt1)begin 61 if(end_cnt1) 62 cnt1 <= 0; 63 else 64 cnt1 <= cnt1 + 1; 65 end 66 else 67 cnt1 <= cnt1; 68 end 69 70 assign add_cnt1 = end_cnt0; 71 assign end_cnt1 = add_cnt1 && cnt1==NUM-1 ; 72 73 //---------------------------------------------------------------------- 74 //-- 每2秒计1次,计到4秒共需计2次 75 //---------------------------------------------------------------------- 76 always @(posedge clk or negedge rst_n)begin 77 if(!rst_n)begin 78 cnt2 <= 0; 79 end 80 else if(add_cnt2)begin 81 if(end_cnt2) 82 cnt2 <= 0; 83 else 84 cnt2 <= cnt2 + 1; 85 end 86 else 87 cnt2 <= cnt2; 88 end 89 90 assign add_cnt2 = end_cnt1; 91 assign end_cnt2 = add_cnt2 && cnt2==2-1 ; 92 93 //---------------------------------------------------------------------- 94 //-- 设置pwm的占空比时间 95 //---------------------------------------------------------------------- 96 always @(posedge clk or negedge rst_n) begin 97 if(!rst_n) 98 pwm_high <= 0; 99 else if(cnt2==0 && end_cnt0) 100 pwm_high <= pwm_high + STEP; 101 else if(cnt2==1 && end_cnt0) 102 pwm_high <= pwm_high - STEP; 103 else 104 pwm_high <= pwm_high; 105 end 106 107 //---------------------------------------------------------------------- 108 //-- 输出led灯 109 //---------------------------------------------------------------------- 110 assign led = (cnt0 < pwm_high) ? 1'b1 : 1'b0; 111 112 113 114 endmodule
二、仿真文件
1 `timescale 1ns/1ps //时间精度 2 `define Clock 20 //时钟周期 3 4 module breathing_led_tb; 5 6 //---------------------<端口定义>--------------------------------------- 7 reg clk ; //时钟,50Mhz 8 reg rst_n ; //复位,低电平有效 9 wire led ; 10 11 //---------------------------------------------------------------------- 12 //-- 模块例化 13 //---------------------------------------------------------------------- 14 breathing_led 15 #( 16 .TIME_2MS (1000 ), //2ms时间 100_000 17 .NUM (100 ), //2ms到2s为1000份 18 .STEP (10 ) //2ms也分成1000份,每份为步长100 19 ) 20 u_breathing_led 21 ( 22 .clk (clk ), 23 .rst_n (rst_n ), 24 .led (led ) 25 ); 26 27 //---------------------------------------------------------------------- 28 //-- 时钟信号和复位信号 29 //---------------------------------------------------------------------- 30 initial begin 31 clk = 1; 32 forever 33 #(`Clock/2) clk = ~clk; 34 end 35 36 initial begin 37 rst_n = 0; #(`Clock*20+1); 38 rst_n = 1; 39 end 40 41 42 43 44 endmodule
三、仿真波形
可以看到led信号的占空比先不断增加后不断减少,循环反复。
四、上板验证
经过上板验证,最终成功!