[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA基础篇连载-06 PWM呼吸灯实验

文档创建者:FPGA课程
浏览次数:251
最后更新:2024-08-21
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 1-FPGA基础入门实验
本帖最后由 FPGA课程 于 2024-8-22 19:46 编辑

​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
小小呼吸灯在很多设备上我们可以看到,我们可以在FPGA的控制主板上也可以加入呼吸灯,指示我们的FPGA主板正在运行。一般呼吸灯的亮灭周期是2S,呼吸灯的亮度可以通过PWM来调节。本文实现一个实用的小程序,读者完全可以自己编写代码,并且通过仿真测试代码的正确性,然后下载到开发板看实际运行效果。
2 硬件电路分析
硬件接口和子卡模块请阅读“附录 1”
配套工程的 FPGA PIN 脚定义路径为 fpga_prj/uisrc/04_pin/ fpga_pin.xdc。
3PWM呼吸灯程序设计3.1系统框图
PWM呼吸灯程序设计中包含了3个定时计数器:
20us定时器,作为本系统的基本定时器,产生时间基准。
20ms定时器,通过20us定时器,计数100次完成20ms定时计数
2s定时器,通过20ms定时器,计数100次完成2S定时计数
PWM每间隔2ms更新一次,共计更新100次即2S后切换PWM的占空比调整方向。因此PWM占空比的调整是和2ms定时计数器和2S定时计数器相关。系统框图如下:
83c6a39c15664b8fafc78ee176ccc45e.jpg
3.2程序源码
  1. `timescale 1ns / 1ns

  2. module pwm_light#
  3. (
  4. parameter REF_CLK      = 32'd100_000_000
  5. )
  6. (
  7. input       I_sysclk_p,
  8. input       I_sysclk_n,
  9. input       I_rstn,
  10. output      O_pwm
  11. );

  12. localparam T20US_SET     = REF_CLK/20000 - 1;  //set 20us
  13. localparam T20MS_SET     = 100 - 1;           //set 20ms
  14. localparam PWM_SET       = 100 - 1;           //Set PWM duty cycle adjustment times

  15. wire I_clk;
  16. IBUFGDS CLK_U(
  17. .I(I_sysclk_p),
  18. .IB(I_sysclk_n),
  19. .O(I_clk)
  20. );

  21. reg [23:0] t20us_cnt;
  22. reg [9 :0] t20ms_cnt;
  23. reg [9 :0] pwm_cnt;
  24. reg PWM_S;

  25. wire t20us_done;
  26. wire t20ms_done;
  27. //设置20us计数,当计数条件达成时拉高
  28. assign t20us_done = (t20us_cnt == T20US_SET);
  29. ///设置20ms计数,当计数条件达成时拉高
  30. assign t20ms_done = t20us_done & (t20ms_cnt == T20MS_SET) ;

  31. //1us base timer
  32. always @(posedge I_clk or negedge I_rstn)begin
  33.     if(I_rstn == 1'b0)
  34.         t20us_cnt <= 0;   
  35.     else if(t20us_cnt < T20US_SET)                   //t20us_cnt寄存器用来计数,目标值是T20US_SET
  36.         t20us_cnt <= t20us_cnt + 1'b1;                              //未达到目标值+1
  37.     else
  38.         t20us_cnt <= 24'd0;                                          //达到目标值清零
  39. end
  40. //1ms pwm compare timer,based on 1us base timer
  41. always @(posedge I_clk or negedge I_rstn)begin                  //系统时钟的上升沿以及复位的下降沿触发
  42.     if(I_rstn == 1'b0)                                                //复位清零
  43.          t20ms_cnt <= 0;   
  44.     else if(t20us_done)                          //t20us_done计数完成作为后续判断的大前提
  45.          t20ms_cnt <= (t20ms_cnt < T20MS_SET) ? (t20ms_cnt + 1'b1) : 10'd0;   //判断语句,当t20ms_cnt < T20MS_SET满足时
  46.     else                                                          //t20ms_cnt计数器+1,否则就清零
  47.          t20ms_cnt <= t20ms_cnt;
  48. end

  49. //PWM counter for generating duty cycle parameters as well as PWM adjustment count
  50. always @(posedge I_clk or negedge I_rstn)begin             //系统时钟的上升沿以及复位的下降沿触发
  51.     if(I_rstn == 1'b0)                                                             //复位清零
  52.         pwm_cnt <= 0;
  53.     else if(t20ms_done)                                    //t20ms_done计数完成作为后续判断的大前提
  54.         pwm_cnt <= (pwm_cnt < PWM_SET) ? (pwm_cnt + 1'b1) : 10'd0; //判断语句,当pwm_cnt < PWM_SET满足时
  55.     else                      //pwm_cntt计数器+1,否则就清零
  56.         pwm_cnt <= pwm_cnt;                                                        
  57. end

  58. //switch breathing state
  59. always @(posedge I_clk or negedge I_rstn)begin         //系统时钟的上升沿以及复位的下降沿触发
  60.     if(I_rstn == 1'b0)
  61.         PWM_S <= 0;                                                            //复位清零
  62.     else if(t20ms_done && (pwm_cnt == PWM_SET))    //pwm_cnt == PWM_SET达成时,对PWM_S的状态进行翻转
  63.         PWM_S <= ~PWM_S;                     //反应到LED灯上是LED灯的亮灭变换转换
  64.     else
  65.         PWM_S <= PWM_S;
  66. End

  67. //添加ila IP ,Chipscope观察信号
  68. ila_0 ila_debug (
  69.     .clk(I_clk), // input wire clk
  70.     .probe0({t20us_done,O_pwm}) // input wire [1:0]  probe0  
  71. );

  72. //PWM wave generating
  73. assign  O_pwm = PWM_S ? (pwm_cnt >= t20ms_cnt) : (pwm_cnt < t20ms_cnt);         //判断语句,通过PWM_S的变换,使O_pwm输出的

  74. endmodule
复制代码

4RTL仿真4.1添加仿真测试源码
仿真测试文件存放在工程目录uisrc\02_sim中,源码如下:
  1. `timescale 1ns / 1ns

  2. module tb_pwm_light();

  3. reg I_sysclk_p,I_sysclk_n,I_rstn;
  4. wire  O_pwm;
  5. pwm_light#
  6. (
  7. .REF_CLK(100_000)   //调小时间参数,加快仿真速度
  8. )
  9. pwm_light_inst
  10. (
  11. .I_sysclk_p(I_sysclk_p), //例化接口
  12. .I_sysclk_n(I_sysclk_n),
  13. .I_rstn(I_rstn),
  14. .O_pwm(O_pwm)
  15. );

  16. initial begin
  17.    I_sysclk_p  <= 1'b0;   //系统时钟设置初值
  18.    I_sysclk_n  <= 1'b1;
  19.    I_rstn    <= 1'b0;    //复位信号设置初值
  20.    #100;
  21.    I_rstn    <= 1'b1;    //复位信号拉高,复位完成
  22. end

  23. always #5 I_sysclk_p=~I_sysclk_p;//时钟定时翻转
  24. always #5 I_sysclk_n=~I_sysclk_n;

  25. endmodule`timescale 1ns / 1ns

  26. module tb_pwm_light();
  27. reg I_sysclk_p,I_sysclk_n,I_rstn;
  28. wire  O_pwm;
  29. pwm_light#
  30. (
  31. .REF_CLK(100_000)   //调小时间参数,加快仿真速度
  32. )
  33. pwm_light_inst
  34. (
  35. .I_sysclk_p(I_sysclk_p), //例化接口
  36. .I_sysclk_n(I_sysclk_n),
  37. .I_rstn(I_rstn),
  38. .O_pwm(O_pwm)
  39. );

  40. initial begin
  41.    I_sysclk_p  <= 1'b0;   //系统时钟设置初值
  42.    I_sysclk_n  <= 1'b1;
  43.    I_rstn    <= 1'b0;    //复位信号设置初值
  44.    #100;
  45.    I_rstn    <= 1'b1;    //复位信号拉高,复位完成
  46. end

  47. always #5 I_sysclk_p=~I_sysclk_p;//时钟定时翻转
  48. always #5 I_sysclk_n=~I_sysclk_n;

  49. endmodule
复制代码

为了方便我们仿真观察现象,缩短我们的仿真时长,我们将时钟计数减小1000倍,所以仿真时长与实际时长相差了1000倍。
4.2仿真结果
下图是刚开始的时候可以看到占空比是以减小的趋势调整
c0ec2e562e814474bd72df060182a1bc.jpg
下图是2000us(实际为2s)处,占空比实现从大变小后又开始从小变大
1f071c7e99f54422ad6eec3d273255c3.jpg
下图是4000us(实际为4s)处,一个周期完成,占空比再次从最大开始往小调整。
ae60648945ad47768db7481593fa27eb.jpg

5在线仿真Captrue模式采样
添加ila在线逻辑分析仪的IP核
67f5040784264e6688d926fd5416a649.jpg
采用Capture Control功能,利用t20us_done作为Capture的采样触发信号,这是我们第一次实现Capture Control功能,对于Ila 低于20M的采样时钟会不能正常工作,但是可以用高采样时钟,配合Capture功能,实现低频的采样,合理利用采样深度。
148e2827eee540a2bfc1437d4c22cd0c.jpg
设置位宽
3b470c85234c4238ae2b76965a3f0ea2.jpg
下载程序后,设置Capture mode为BASIC
28c58f88dcf245c9a9def02980b17a2b.jpg
设置采样条件t20us_done为1的时候进行采样
559e4afc7cc843c4b9238aba797ec629.jpg
根据设置条件开始采样
6d636e49f76f42e1ab226d3479cd336f.jpg
占空比变化明显
e97a2804eec24e599f08309f647f084d.jpg
6实验结果
(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)
请确保下载器和开发板已经正确连接,另外需要把核心板上的2P模式开关设置到JTAG模式,即ON ON,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

可以看到LED呼吸灯的亮灭变化
595ec0405e7f4643addcb5950461236d.jpg


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则