当前位置:   article > 正文

zynq学习之fpga篇(四)数码管动态显示_数码管动态显示fpga

数码管动态显示fpga

一、设计要求

拨码开关的开闭充当1与0,总的使用4个拨码开关,将其所组成二进制,使用六位数码管最高位进行十进制显示,后四位显示拨码开关所对应的BCD码。

解析

(1)十进制对应BCD码
8421码十进制数
00000
00011
00102
00113
01004
01015
01106
01117
10008
10019
 (2)数码管显示原理

数码管显示分为静态显示和动态显示,静态显示所有数码管显示相同的数值,动态显示不同数码管显示不同数值。

静态显示:控制数码管需要控制两个信号,位选信号和段选信号。位选信号是独立控制的,用来控制单个数码管的亮灭。段选信号控制数码管显示数值,在电路中六个数码管的段选信号连接在一起,所以在同一时间,位选信号控制点亮的数码管显示的值是相同的。

动态显示:由“人眼视觉暂留”和“数码管余晖效应”,当我们让每个数码管快速轮流显示,当速度快到人眼无法分辨时,我们所看到的数码管就是同时显示了不同的数值。

二、模块设计

数码管动态显示系统框图

分析

整个系统分为三个模块:

Top_seg顶层模块,连接各模块对应信号
data_change数据转化模块,将拨码开关对应二进制转化为数字信号
Seg_dynamic动态数码管扫描模块

三、波形设计

data_change模块波形设计

分析

Data_BCD信号将四个输入转为二进制编码,seg_en信号为控制数码管动态扫描信号,在此次项目中可一直拉高。

Seg_dynamic模块波形设计

分析 

在编写过程中,想到时序逻辑,数据会延迟一拍,为了保证数据同步需要编写寄存器,用来寄存数据。

四、代码编写

顶层模块 

  1. module top_seg(
  2. input wire sys_clk ,
  3. input wire sys_rst_n ,
  4. input wire key_in_0 ,
  5. input wire key_in_1 ,
  6. input wire key_in_2 ,
  7. input wire key_in_3 ,
  8. output wire [5:0] sel ,
  9. output wire [7:0] seg
  10. );
  11. wire [3:0] data_bcd ;
  12. wire seg_en ;
  13. data_change data_change_inst(
  14. .sys_clk (sys_clk ) ,
  15. .sys_rst_n (sys_rst_n ),
  16. .key_in_0 (key_in_0 ),
  17. .key_in_1 (key_in_1 ),
  18. .key_in_2 (key_in_2 ),
  19. .key_in_3 (key_in_3 ),
  20. .data_bcd (data_bcd ),
  21. .seg_en (seg_en )
  22. );
  23. seg_dynamic seg_dynamic_inst(
  24. .sys_clk (sys_clk ),
  25. .sys_rst_n (sys_rst_n ),
  26. .data_bcd (data_bcd ),
  27. .seg_en (seg_en ),
  28. .sel (sel ),
  29. .seg (seg )
  30. );
  31. endmodule

 数据转化模块:

  1. module data_change(
  2. input wire sys_clk ,
  3. input wire sys_rst_n ,
  4. input wire key_in_0 ,
  5. input wire key_in_1 ,
  6. input wire key_in_2 ,
  7. input wire key_in_3 ,
  8. output reg [3:0] data_bcd ,
  9. output reg seg_en
  10. );
  11. always@(posedge sys_clk or negedge sys_rst_n)
  12. if(!sys_rst_n)begin
  13. data_bcd <= 4'd0;
  14. seg_en <= 1'b0;
  15. end
  16. else begin
  17. data_bcd <= {key_in_0,key_in_1,key_in_2,key_in_3};
  18. seg_en <= 1'b1;
  19. end
  20. endmodule

数码管动态扫描模块:

  1. module seg_dynamic(
  2. input wire sys_clk ,
  3. input wire sys_rst_n ,
  4. input wire [3:0] data_bcd,
  5. input wire seg_en ,
  6. output reg [5:0] sel ,
  7. output reg [7:0] seg
  8. );
  9. parameter CNT_MAX = 16'd49_999;
  10. reg [24:0] cnt_1ms ;
  11. reg cnt_flag ;
  12. reg [2:0] cnt_sel ;
  13. reg [5:0] sel_reg ;
  14. reg [3:0] data_reg ;
  15. always@(posedge sys_clk or negedge sys_rst_n)
  16. if(!sys_rst_n)
  17. cnt_1ms <= 16'd0;
  18. else if(cnt_1ms==CNT_MAX)
  19. cnt_1ms <= 16'd0;
  20. else
  21. cnt_1ms <= cnt_1ms + 1'b1;
  22. always@(posedge sys_clk or negedge sys_rst_n)
  23. if(!sys_rst_n)
  24. cnt_flag <= 1'b0;
  25. else if(cnt_1ms==CNT_MAX-1)
  26. cnt_flag <= 1'b1;
  27. else
  28. cnt_flag <= 1'b0;
  29. always@(posedge sys_clk or negedge sys_rst_n)
  30. if(!sys_rst_n)
  31. cnt_sel <= 3'd0;
  32. else if(cnt_flag==1'b1)
  33. cnt_sel <= cnt_sel + 1'b1;
  34. else if((cnt_sel==3'd5)&&(cnt_flag==1'b1))
  35. cnt_sel <= 3'd0;
  36. else
  37. cnt_sel <= cnt_sel;
  38. always@(posedge sys_clk or negedge sys_rst_n)
  39. if(!sys_rst_n)
  40. sel_reg <= 6'd0 ;
  41. else case(cnt_sel)
  42. 3'b000 : sel_reg <= 6'b111_110 ;
  43. //3'b001 : sel_reg <= 6'b111_101 ;
  44. 3'b010 : sel_reg <= 6'b111_011 ;
  45. 3'b011 : sel_reg <= 6'b110_111 ;
  46. 3'b100 : sel_reg <= 6'b101_111 ;
  47. 3'b101 : sel_reg <= 6'b011_111 ;
  48. default sel_reg <= 6'b111_111 ;
  49. endcase
  50. always@(posedge sys_clk or negedge sys_rst_n)
  51. if(!sys_rst_n)
  52. data_reg <= 3'd0 ;
  53. else case(cnt_sel)
  54. 3'b000 : data_reg <= data_bcd ;
  55. //3'b001 : data_reg <= 6'b000_010 ;
  56. 3'b010 : data_reg <= {4'b00,data_bcd[3]} ;
  57. 3'b011 : data_reg <= {4'b00,data_bcd[2]} ;
  58. 3'b100 : data_reg <= {4'b00,data_bcd[1]} ;
  59. 3'b101 : data_reg <= {4'b00,data_bcd[0]} ;
  60. default data_reg <= 4'b0000 ;
  61. endcase
  62. always@(posedge sys_clk or negedge sys_rst_n)
  63. if(!sys_rst_n)
  64. seg <= 8'h79 ;
  65. else case(data_reg)
  66. 4'd0 : seg <= 8'h3f;
  67. 4'd1 : seg <= 8'h06;
  68. 4'd2 : seg <= 8'h5b;
  69. 4'd3 : seg <= 8'h4f;
  70. 4'd4 : seg <= 8'h66;
  71. 4'd5 : seg <= 8'h6d;
  72. 4'd6 : seg <= 8'h7d;
  73. 4'd7 : seg <= 8'h07;
  74. 4'd8 : seg <= 8'h7f;
  75. 4'd9 : seg <= 8'h6f;
  76. default seg <= 8'h79 ;
  77. endcase
  78. always@(posedge sys_clk or negedge sys_rst_n)
  79. if(!sys_rst_n)
  80. sel <= 6'd0;
  81. else
  82. sel <= sel_reg;
  83. endmodule

五、RTL视图

由RTL视图发现该代码有待改进,多路选择部分没有写完整。 

六、Testbench编写

  1. module tb_seg();
  2. reg sys_clk ;
  3. reg sys_rst_n ;
  4. reg key_in_0 ;
  5. reg key_in_1 ;
  6. reg key_in_2 ;
  7. reg key_in_3 ;
  8. wire [5:0] sel ;
  9. wire [7:0] seg ;
  10. initial
  11. begin
  12. sys_clk <= 1'b1;
  13. sys_rst_n <= 1'b0;
  14. key_in_0 <= 1'b0;
  15. key_in_1 <= 1'b0;
  16. key_in_2 <= 1'b0;
  17. key_in_3 <= 1'b0;
  18. #20
  19. sys_rst_n <= 1'b1;
  20. end
  21. always#10 sys_clk <= ~sys_clk;
  22. always#100_0007 key_in_1 <= {$random} % 2;
  23. always#100_0007 key_in_2 <= {$random} % 2;
  24. always#100_0007 key_in_3 <= {$random} % 2;
  25. top_seg top_seg_inst(
  26. .sys_clk (sys_clk ) ,
  27. .sys_rst_n (sys_rst_n),
  28. .key_in_0 (key_in_0),
  29. .key_in_1 (key_in_1),
  30. .key_in_2 (key_in_2),
  31. .key_in_3 (key_in_3),
  32. .sel (sel) ,
  33. .seg (seg)
  34. );
  35. endmodule

七、仿真结果

仿真波形图

仿真波形主要查看动态数码管扫描模块部分是否正确。 

八、上板实测

上板实测

 如图所示,用左下方四个拨码开关进行输入,数码管进行输出。

九、下期内容

没有系统的跟谁学习,每次做完一个项目不知道下个项目学什么,每次都提前想好吧!

下个项目FPGA部分最后一个项目——摄像头驱动,可以学到:IIC通信协议、SPI通信协议、UART通信、FIFO、SDRAM 等等。

行而不辍,未来可期。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/738613
推荐阅读
相关标签
  

闽ICP备14008679号