FPGA|CPLD|ASICwilliam hill官网
直播中

Legen

6年用户 3经验值
擅长:嵌入式技术,处理器/DSP
私信 关注
[经验]

【FPGA开发者项目连载】Led流水灯小程序测试

1.简介
       本次led流水灯实验是基于MINI_STAR_4K开发板,并且以高云半导体独家秘制的GOWIN云源软件为编译工具而实现。实验结果验证了该开发板和eda工具的可行性。实验成果展示在最底部。
2.环境

  • Windows 10 64位
  • MINI_STAR_4K开发板
  • 云源软件 for win V1.9.7.03 Beta

3.程序设计
       开发板上有两个led灯(高电平点亮),设定四种闪烁组合模式,模式一:led[0]和led[1]的亮灭周期都是一秒,交替闪烁。模式二:两个灯亮灭周期都是半秒,交替闪烁。 模式三:两灯亮灭周期都是半秒,同亮同灭。模式三:一个灯亮灭周期是一秒,另一个灯亮灭周期是半秒,一快一慢闪烁。

       3.1 led计数器:设定两个计数器,一个计数器控制一个led。当时钟频率是25 MHz(周期是40ns)时,led延时计数器计数12500000个时钟周期为一秒,计数6250000个时钟周期为一秒。开发板上的晶振是27 MHz,这里设定12500000个时钟周期延时其实不够一秒钟,但这种试验要求没那么严格,可用。
  1.     //led[0] 延时计数器
  2.     always @(posedge clk or negedge rst_n) begin
  3.         if (rst_n == 1'b0)
  4.             cnt <= 24'b0  ;            

  5.         else if (add_cnt) begin
  6.             if (end_cnt)
  7.                 cnt <= 24'b0 ;
  8.             else
  9.                 cnt <= cnt + 1'b1;
  10.         end
  11.     end

  12.     assign add_cnt = 1 ;
  13.     assign end_cnt = add_cnt && cnt == total-1;

  14.     //led[1]延时计数器
  15.     always @(posedge clk or negedge rst_n) begin
  16.         if (rst_n == 1'b0)
  17.             cnt2 <= 24'b0  ;            

  18.         else if (add_cnt2) begin
  19.             if (end_cnt2)
  20.                 cnt2 <= 24'b0 ;
  21.             else
  22.                 cnt2 <= cnt2 + 1'b1;
  23.         end
  24.     end

  25.     assign add_cnt2 = 1 ;
  26.     assign end_cnt2 = add_cnt2 && cnt2 == total_2-1;

      3.2 模式切换计数器:模式切换计数器一在led[0]亮灭一次后加一,计数十次。模式切换计数器二在模式切换计数器一计数满时加一,计数四次。
  1. always @(posedge clk or negedge rst_n) begin
  2.     if (rst_n == 1'b0)
  3.          cnt_model <= 4'b0  ;
  4.     else if (add_cnt_model) begin
  5.          if (end_cnt_model)
  6.              cnt_model <= 4'b0 ;
  7.          else
  8.              cnt_model <= cnt_model + 1'b1;
  9.          end
  10.   end

  11.     assign add_cnt_model = end_cnt ;        //  led[0] 闪烁一次加一次一
  12.     assign end_cnt_model = add_cnt_model && cnt_model == 9;

  13.     always @(posedge clk or negedge rst_n) begin
  14.      if (rst_n == 1'b0)
  15.           wave_mode <= 2'b0  ;
  16.      else if (add_wave_mode) begin
  17.           if (end_wave_mode)
  18.                wave_mode <= 2'b0 ;
  19.           else
  20.                wave_mode <= wave_mode + 1'b1;
  21.           end
  22.   end

  23.     assign add_wave_mode = end_cnt_model ;   //   前一级计数器计满一次加一次一
  24.     assign end_wave_mode = add_wave_mode && wave_mode == 3;
      
      3.3 led控制:使用组合逻辑,根据模式切换计数器二的值更改两个led计数器的最大计数值,以及两个led的亮灭规律。代码如下(一种模式实现方式已注释):
  1.     // 设定led[0]在计数半周期和整周期的状态
  2.     always @(posedge clk or negedge rst_n) begin
  3.         if(!rst_n) begin
  4.             led[0] <= 1'b0;
  5.         end
  6.         else if(cnt == total/2-1) begin
  7.             led[0] <= wave_1;
  8.         end
  9.         else if(cnt == total-1)begin
  10.             led[0] <= wave_2 ;
  11.         end
  12.     end

  13.     // 设定led[1]在计数半周期和整周期的状态
  14.     always @(posedge clk or negedge rst_n) begin
  15.         if(!rst_n) begin
  16.             led[1] <= 1'b0;
  17.         end
  18.         else if(cnt2 == total_2 / 2 - 1) begin
  19.             led[1] <= wave_1_2 ;
  20.         end
  21.         else if(cnt2 == total_2 - 1)begin
  22.             led[1] <= wave_2_2 ;
  23.         end
  24.     end
  25.    
  26.     // 实现不同模式下led的闪烁组合
  27.     always @(*) begin
  28.         if(!rst_n)begin
  29.             total = 0;   
  30.             total_2 = 0;
  31.             wave_1 = 1'b0;
  32.             wave_2 = 1'b0;
  33.             wave_1_2 = 1'b0;
  34.             wave_2_2 = 1'b0;
  35.         end
  36.         // 此模式下 led[0]和led[1]亮灭周期都是半秒,交替闪烁
  37.         else if (wave_mode == 0) begin  
  38.             total = 6250000;            
  39.             total_2 = 6250000;
  40.             wave_1 = 1'b0;              // led[0]在半周期时灭
  41.             wave_2 = 1'b1;              // led[0]在全周期时亮
  42.             wave_1_2 = 1'b1;            // led[1]在半周期时亮
  43.             wave_2_2 = 1'b0;            // led[1]在全周期时灭
  44.         end
  45.         else if (wave_mode == 1)begin
  46.             total = 12500000;
  47.             total_2 = 6250000;
  48.             wave_1 = 1'b0;
  49.             wave_2 = 1'b1;
  50.             wave_1_2 = 1'b1;
  51.             wave_2_2 = 1'b0;
  52.         end
  53.         else if (wave_mode == 2) begin
  54.             total = 6250000;
  55.             total_2 = 6250000;
  56.             wave_1 = 1'b1;
  57.             wave_2 = 1'b0;
  58.             wave_1_2 = 1'b1;
  59.             wave_2_2 = 1'b0;
  60.         end
  61.         else if (wave_mode == 3) begin
  62.             total = 12500000;
  63.             total_2 = 12500000;
  64.             wave_1 = 1'b1;
  65.             wave_2 = 1'b0;
  66.             wave_1_2 = 1'b1;
  67.             wave_2_2 = 1'b0;
  68.         end
  69.         else  begin
  70.             total = 0;
  71.             total_2 = 0;
  72.             wave_1 = 1'b0;
  73.             wave_2 = 1'b0;
  74.             wave_1_2 = 1'b0;
  75.             wave_2_2 = 1'b0;
  76.         end
  77.     end

3.4 结语       最初想着把按键消抖模块调用进来,用按键控制led灯的闪烁模式,各模块儿仿真都成功了,不过最终未遂。之后修改的程序,设定成延期一段时间自动跳转状态,搞得程序中的名称有些乱。好消息是,通过这一段小程序的编写,我发现了个很基础问题,之前一直没注意:笔记https://www.notion.so/Verilog-29f34f2560294bea8acfaa26f535eed4
4. GOWIN云源软件说明
云源软件的使用感受:感觉它挺像vivado的,界面很简洁,看着十分清爽。仿真麻烦了点,需借用Multisim,我干脆用vivado创建的工程,仿真完成后再搬过来用的。

软件使用方法:B站搜索Myminieye ,进入TA的视频,会看到详细的软件使用教程,包括软件安装的步骤,视频远比文字描述直观。

















led闪烁效果

回帖(1)

Legen

2021-5-13 10:00:06
Verilog中不支持参数动态调整
举报

更多回帖

发帖
×
20
完善资料,
赚取积分