FPGA|CPLD|ASICwilliam hill官网
直播中

熊朝帅

12年用户 97经验值
擅长:嵌入式技术,控制/MCU
私信 关注

【FPGA开发者项目连载】LED旋转显示-软件篇

测试ROM效果

` 本帖最后由 cxzs1234 于 2021-7-11 22:45 编辑

今天是周末,调试了半天程序,终于可以显示了,现在做一下总结。
在编程序前要解决一个问题是下载问题,之前遇到不能下载的情况,一直困扰了几天。后来发现可以直接使用开发板的JTAG接口下载就可以,也就是相当于和板上的FPGA并联。之前看文档说是可以联试连接,没想到可以并联。要识别MINI STAR上的仿真器,需要在下载界面中Edit->Cable点击Query,就可以识别出开发板的JTAG,下载速度可选,比之前SPIEED的开发工具好用和快很多。
21.png
首先需要显示什么汉字,既然是高云组织的活动,就显示一个“高云FPGA”,高云汉字简单,12的高度可以正常显示出来,这样通过字模软件获取数据,并通过其它软件将数据整理。
22.png
最后按照高云在《Gowin 存储器(B-SRAM & S-SRAM)用户指南》最后一章怎么初始化数据文件的,制作好 font.mi文件,保存到工程目录中。
23.png
其次在设计中需要用到存储器,就是使用IP Core Generator 生成一个pROM,这个操作简单,使用也很方便。填写数据,点确定就行了。地址深度(Address Depth)也就是有多少字节存储,12*4=48,数据宽度(Data Width)选择16,需要说明的是这个数据宽度只能位1,2,4,8,16,32。因为配置其他的都会自动的大一号,比如填写12,最后自动改为16。最后找到刚才写的font.mi文件,系统就自动生成一个文件,把初始化的数据都填进去了。
24.png
25.png
最后写一个测试程序测试一下读取到的数据是否按自己的要求显示出来.
测试ROM的Top.v
  1. module demo (
  2.     output [11:0] led
  3. );

  4. wire sys_clk;
  5. reg  [11:0] led =12'h001;
  6. reg  [5:0] adress = 6'b000000;
  7. wire  [15:0] displayData;
  8. wire reset_n;
  9. reg  ce;
  10. wire oce ;
  11. assign reset = 1'b0;
  12. assign oce = 1'b1;
  13. Gowin_OSC sysClk(.oscout(sys_clk)); //output oscout

  14. Gowin_pROM font_rom(
  15.         .dout(displayData), //output [15:0] dout
  16.         .clk(sys_clk), //input clk
  17.         .oce(oce), //input oce
  18.         .ce(ce), //input ce
  19.         .reset(reset), //input reset
  20.         .ad(adress));//input [5:0] adress
  21.    
  22. reg[23:0] counter =24'h0;
  23.    
  24. always @(posedge sys_clk )
  25. begin
  26.     if (counter < 24'd1200_0000)       // 0.5s delay
  27.         counter <= counter + 1;
  28.     else
  29.         counter <= 24'd0;
  30. end
  31.    
  32. always @(posedge sys_clk )
  33. begin
  34.     if (counter == 24'd1199_9997)       // 0.5s delay
  35.         led[11:0] <= displayData[11:0];
  36.     else
  37.         led <= led;
  38. end
  39. //使能存储器
  40. always @(posedge sys_clk )
  41. begin
  42.     if(counter == 24'd1199_9995)
  43.         ce <= 1'b1;
  44.     else if(counter == 24'd1199_9999)
  45.         ce <= 1'b0;
  46.     else
  47.         ce <= ce;
  48. end
  49. //生成地址
  50. always @(posedge sys_clk )
  51. begin
  52.     if(counter == 24'd1199_9999)
  53.        if(adress == 6'd48)
  54.             adress <= 0;
  55.        else
  56.             adress <= adress +1;
  57.     else
  58.         adress <= adress;
  59. end

  60. endmodule
在代码中没有用到reset,需要把它直接接0,这个是高电平复位。
这样就看到数据以0.5S的速度一个一个的显示出来。

数据在可以正常显示了,只要加快速度,且配合位置开关和一些时序程序就行了。
为了显得更专业些,这次进行分层编写程序,将显示部分单独出来,形成Display.v,并在Top.v中实例化。同时增加了如果长时间不转动就关闭功能,省电为主,因为纽扣电池电量有限啊。同时生成了一个2分频的时钟信号,传递给Display,也是像实验一下,没有多大的含义。
Top.v
  1. module demo (
  2.     input pos,
  3.     output pow_en,
  4.     output [11:0] led_out
  5. );

  6. wire sys_clk;

  7. Gowin_OSC osc_clk(.oscout(sys_clk)); //output oscout
  8. wire led_clk_div2;
  9. Gowin_CLKDIV led_clk(
  10.         .clkout(led_clk_div2), //output clkout
  11.         .hclkin(sys_clk), //input hclkin
  12.         .resetn(1'b1) //input resetn
  13.     );
在Display.v中,使用了三段式状态机,比较常用的状态机,同时在该文件中实例化之前的ROM。通过状态机完成对ROM的读和LED显示时序按逻辑进行,还可以再优化一下,是程序更简练。
Display.v
  1. module DisplayLED (
  2.     input led_clk,
  3.     input position,   //用于计时本次转速 后期实现根据转速控制显示时间  达到转速下降时显示面积不变
  4.     //input display_start,
  5.     //output display_over,
  6.     output [11:0] led_out
  7. );
  8. //初始化ROM
  9. reg  [11:0] get_led_data =12'h0;
  10. reg  [5:0] font_rom_adress_r;//ROM地址
  11. wire [5:0] font_rom_adress_w;
  12. wire [15:0] display_data;
  13. wire reset;
  14. assign reset = 1'b0;  //置高才是复位
  15. wire oce ;
  16. assign oce = 1'b1;

  17. reg  font_rom_ce;
  18. //显示数据ROM实例化
  19. Gowin_pROM font_rom(
  20.         .dout(display_data), //output [15:0] dout
  21.         .clk(led_clk), //input clk
  22.         .oce(oce), //input oce
  23.         .ce(font_rom_ce), //input ce
  24.         .reset(reset), //input reset
  25.         .ad(font_rom_adress_w));//input [5:0] adress

  26. //LED显示状态机---三段式
  27. parameter     IDLE   = 3'd0 ;
  28. parameter     START  = 3'd1 ;
  29. parameter     REDA   = 3'd2 ;
  30. parameter     OUT    = 3'd3 ;
  31. parameter     NEXT   = 3'd4 ;

  32. reg[15:0] led_hold_time =16'h0;//LED保持时间
  33. reg  hold_time_end;
  34. always @(posedge led_clk )
  35. begin
  36.     if (led_hold_time < 16'd12500)       // 1ms delay
  37.         begin
  38.             led_hold_time <= led_hold_time + 1;
  39.             hold_time_end <= 0;
  40.         end
  41.     else
  42.         begin
  43.             led_hold_time <= 0;
  44.             hold_time_end <= 1;
  45.         end
  46. end
  47. //内部信号声明
  48. reg[2:0] current_state;
  49. reg[2:0] next_state;

  50. reg led_display_start_r;  
  51. //状态寄存器
  52. always @ (posedge led_clk )
  53. begin
  54.     current_state <= next_state;
  55. end  
  56. //次态的组合逻辑
  57. always @ (*)
  58. begin
  59.     case(current_state)
  60.         IDLE:   begin  //空闲状态
  61.                     if(position == 0) //霍尔传感器到来
  62.                         next_state = START;
  63.                     else   
  64.                         next_state = IDLE;
  65.                 end
  66.         START:  begin  //起始信号  
  67.                     if(position == 1) //霍尔传感器离开
  68.                         next_state = REDA;
  69.                     else   
  70.                         next_state = START;
  71.                 end
  72.         REDA:   begin  //读取数据  使能读取数据
  73.                     next_state = OUT;
  74.                 end
  75.         OUT:    begin  //LED输出数据
  76.                     if(hold_time_end)
  77.                         next_state = NEXT;
  78.                     else   
  79.                         next_state = OUT;
  80.                 end
  81.         NEXT:   begin  //结束显示
  82.                     if(led_display_start_r)
  83.                         next_state = REDA;
  84.                     else   
  85.                         next_state = IDLE;
  86.                 end
  87.         default : next_state = IDLE;
  88.    endcase
  89. end

  90. //输出逻辑
  91. always @ (posedge led_clk)
  92. begin
  93.     case(current_state)
  94.         IDLE:   begin  //空闲状态
  95.                     font_rom_ce <= 0;
  96.                     get_led_data[11:0] <= 12'd0;
  97.                     font_rom_adress_r <= 0;
  98.                     led_display_start_r <= 0;
  99.                 end
  100.         START:  begin  //起始信号
  101.                   led_display_start_r <= 1;
  102.                 end
  103.         REDA:   begin  //使能读取数据
  104.                     font_rom_ce <= 1;  
  105.                 end
  106.         OUT:  begin  //LED输出数据
  107.                     get_led_data[11:0] <= display_data[11:0];
  108.              end
  109.         NEXT:   begin  //结束显示
  110.                     font_rom_ce <= 0;
  111.                     if(font_rom_adress_r > 6'd47)
  112.                     begin
  113.                         font_rom_adress_r <= 0;
  114.                         led_display_start_r <= 0;//播放完毕标志
  115.                     end
  116.                     else
  117.                     begin  //进行地址递增
  118.                         font_rom_adress_r <= font_rom_adress_r +1;
  119.                         led_display_start_r <= led_display_start_r;
  120.                     end   
  121.                 end
  122.         default:begin  //空闲状态
  123.                     font_rom_ce <= 0;
  124.                     get_led_data[11:0] <= 12'd0;
  125.                     font_rom_adress_r <= 0;
  126.                 end
  127.     endcase
  128. end
  129. assign font_rom_adress_w = font_rom_adress_r;
  130. assign led_out = get_led_data;

  131. endmodule
通过综合和配置引脚,最后下载程序,这些步骤省略了,需要注意的是在Place & Route前要对一些多功能引脚进行配置(在Synthesize或者Place & Route上右键最后一项Configuration ),配置为普通IO,如下图所示,否则会出现错误。
29.png
就开始测试结果,基本上达到了实验要求。如视频所示,但是硬件上有点问题,现在总结如下:

1,板子做的有点长,手指短点就很容易碰到。
2,所用瓶盖(放有磁铁)有点软,不是很稳当,要么很容易曾到底部元器件,速度提不上来。或者距离有点远,导致霍尔传感器无法接触到信号,所以出现闪烁现象。其实实际效果比拍摄的要好一点,可以看清文字的。
13.jpg
3、硬件配置威廉希尔官方网站 的两个电阻本应该接VCC的,结果没注意接到了地,也就有了那根红线的诞生,在上传的文件中已经修改了这个问题。
下一步准备将最后的四个APA102亮起来,在此更改打样一下PCB,在重新制作一次。现将本次资料提供如下,欢迎指正。
FidgetSpin_测试ROM.rar (43.43 KB)
(下载次数: 0, 2021-7-11 22:31 上传)

FidgetSpin_OK.rar (51.73 KB)
(下载次数: 1, 2021-7-11 22:31 上传)

FidgetSpinPCBV1.0.rar (120.79 KB)
(下载次数: 0, 2021-7-11 22:31 上传)


` 12.jpg

最终效果

更多回帖

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