当前位置:   article > 正文

【FPGA/verilog -入门学习15】vivado FPGA 数码管显示_vivado数码管显示

vivado数码管显示

1,需求:使用xc720 开发板的8个数码管显示12345678

2,需求分析:

75hc595

1,74hc595驱动,将串行数据转换成并行输出。对应研究手册

2,发送之前将要发的数据,合并成高8位:SEG,低8位:SEL, 结合testbanch查看波形,使用测试代码验证显示。

  1. //实现承有数码管显示1
  2. `timescale 1ns/1ps
  3. module vlg_74hc595_v(
  4. input i_clk,
  5. input i_rest_n,
  6. input [15:0]i_data,
  7. output reg o_ds,
  8. output reg o_shcp,
  9. output reg o_stcp
  10. );
  11. //parameter i_sel = 8'b1111_0000;
  12. //parameter i_seg = 8'b1000_0000;
  13. wire clk_25m;
  14. wire clk_12r5m;
  15. wire clk_100m;
  16. wire locked;
  17. clk_wiz_0 clk_div_inst
  18. (
  19. // Clock out ports
  20. .clk_out1(clk_25m), // output clk_out1
  21. .clk_out2(clk_12r5m), // output clk_out2
  22. .clk_out3(clk_100m), // output clk_out3
  23. .reset(~i_rest_n), // input reset
  24. .locked(locked), // output locked
  25. // Clock in ports
  26. .clk_in1(i_clk)); // input clk_in1
  27. //assign i_data[15:8] = i_seg;//seg7,seg6,seg5,seg4,seg3,seg2,seg1,seg0
  28. //assign i_data[7:0] = i_sel;//s7,s6,s5,s4,s3,s2,s1,s0
  29. reg [4:0]r_cnt;//16次计
  30. //产生o_ds 信号
  31. always @(posedge clk_12r5m) begin
  32. if(!i_rest_n) begin
  33. o_ds <= 0;
  34. r_cnt <= 0;
  35. end
  36. else if(locked & r_cnt < 16) begin
  37. o_ds <= i_data[15-r_cnt];
  38. r_cnt <= r_cnt + 1;
  39. end
  40. else begin r_cnt <= 0; o_ds <= 0; end
  41. end
  42. //产生o_shcp
  43. always @(negedge clk_25m) begin
  44. if(!i_rest_n) o_shcp <= 0;
  45. else if(r_cnt== 0) o_shcp <= 0;
  46. else o_shcp <= ~o_shcp;
  47. end
  48. //产生o_stcp
  49. always @(negedge clk_25m) begin
  50. if(!i_rest_n) o_stcp <= 0;
  51. else if(r_cnt== 16 && o_shcp) o_stcp <= 1;
  52. else o_stcp <= 0;
  53. end
  54. endmodule

分频

1,数码管以1Khz 切换1~8个数码管状态。 数码管刷新频率位 1KHZ/8 = 125hz/8ms 刷新一次

2,74hc595 更新bit 速率 12.5Mhz shcp

  1. //实现分屏,12.5M,50K
  2. `timescale 1ns/1ps
  3. module vlg_div(
  4. input i_clk,
  5. input i_rest_n,
  6. output o_clk_12r5m,
  7. output o_clk_1khz //50*20=1000
  8. );
  9. //`define SIMU_FLGA
  10. `ifdef SIMU_FLGA
  11. localparam CLK_12R5M_MAX = 50_000_000/12_500_000 -1;
  12. localparam CLK_1KHZ_MAX = 10-1;
  13. `else
  14. localparam CLK_12R5M_MAX = 50_000_000/12_500_000 -1;
  15. localparam CLK_1KHZ_MAX = 50_000_000/1000 -1;
  16. `endif
  17. //12.5M 计数使能
  18. reg [3:0]r_cnt_12r5m;
  19. always @(posedge i_clk) begin
  20. if(!i_rest_n) r_cnt_12r5m <= 0;
  21. else if(r_cnt_12r5m < CLK_12R5M_MAX) r_cnt_12r5m <= r_cnt_12r5m +1;
  22. else r_cnt_12r5m <= 0;
  23. end
  24. assign o_clk_12r5m = (r_cnt_12r5m == CLK_12R5M_MAX) ?1:0;
  25. //50K 计数使能
  26. reg [19:0]r_cnt_1khz;
  27. always @(posedge i_clk) begin
  28. if(!i_rest_n) r_cnt_1khz <= 0;
  29. else if(r_cnt_1khz < CLK_1KHZ_MAX) r_cnt_1khz <= r_cnt_1khz +1;
  30. else r_cnt_1khz <= 0;
  31. end
  32. assign o_clk_1khz = (r_cnt_1khz == CLK_1KHZ_MAX) ?1:0;
  33. endmodule

数据产生

1,当1kHZ 来临时,合并sel+seg = [15:0]data

2,合并前要将sel 转换成 0000_0001 即每一1 代表要选择的sel

3,合并前将数字转换成数码管 编码

  1. //实现将8个数码管的数值,以20ms 输出seg+sel 的值
  2. `timescale 1ns/1ps
  3. module vlg_data_generate(
  4. input i_clk,
  5. input i_rest_n,
  6. input i_clk_1khz,
  7. input [31:0]i_data, //输入8个数码管的数值 ,每个数码管用4位表示,例如f:1111
  8. output reg[15:0]o_data_seg_sel //输出数码管的seg+sel 高8位seg,低8位sel
  9. );
  10. //产生20ms 的 0-7 计数
  11. reg [7:0]r_index; //0-7
  12. always @(posedge i_clk) begin
  13. if(!i_rest_n) r_index <= 0;
  14. else if(i_clk_1khz) begin
  15. if(r_index < 7) r_index <= r_index + 1;
  16. else r_index <= 0;
  17. end
  18. end
  19. //根据0-7 变换,取出对应的seg 的hex码
  20. reg [3:0]r_hex;
  21. always @(posedge i_clk) begin
  22. if(!i_rest_n) r_hex <= 0;
  23. else
  24. case (r_index)
  25. 4'd0: r_hex <= i_data[3:0];
  26. 4'd1: r_hex <= i_data[7:4];
  27. 4'd2: r_hex <= i_data[11:8];
  28. 4'd3: r_hex <= i_data[15:12];
  29. 4'd4: r_hex <= i_data[19:16];
  30. 4'd5: r_hex <= i_data[23:20];
  31. 4'd6: r_hex <= i_data[27:24];
  32. 4'd7: r_hex <= i_data[31:28];
  33. default r_hex <= 0;
  34. endcase
  35. end
  36. //将hex 变成数码管显示
  37. reg [7:0]r_seg;
  38. always @(posedge i_clk) begin
  39. if(!i_rest_n) r_seg <= 8'b1111_1111;
  40. else
  41. case (r_hex)
  42. 4'h0:r_seg <= 8'b1100_0000;//c0
  43. 4'h1:r_seg <= 8'b1111_1001;//f9
  44. 4'h2:r_seg <= 8'b1010_0100;//a4
  45. 4'h3:r_seg <= 8'b1011_0000;//b0
  46. 4'h4:r_seg <= 8'b1001_1001;//99
  47. 4'h5:r_seg <= 8'b1001_0010;//92
  48. 4'h6:r_seg <= 8'b1000_0010;//82
  49. 4'h7:r_seg <= 8'b1111_1000;//f8
  50. 4'h8:r_seg <= 8'b1000_0000;//80
  51. 4'h9:r_seg <= 8'b1001_0000;//90
  52. 4'ha:r_seg <= 8'b1000_1000;//88
  53. 4'hb:r_seg <= 8'b1000_0011;//83
  54. 4'hc:r_seg <= 8'b1100_0110;//c6
  55. 4'hd:r_seg <= 8'b1010_0001;//a1
  56. 4'he:r_seg <= 8'b1000_0110;//86
  57. 4'hf:r_seg <= 8'b1000_1110;//8e
  58. default:r_seg <= 8'b1111_1111;//ff
  59. endcase
  60. end
  61. //将sel和seg 按 i_clk_50hz组合输出
  62. always @(posedge i_clk) begin
  63. if(!i_rest_n) o_data_seg_sel <= 0;
  64. else if(i_clk_1khz &i_clk) begin
  65. o_data_seg_sel[7:0] <= (1 << r_index); //0-7
  66. o_data_seg_sel[15:8] <= r_seg;
  67. end
  68. else ;
  69. end
  70. endmodule

输入输出

测试代码使用localparam data 赋值形式

正式代码使用vio 输入

  1. //vlg design 显示数码箿
  2. `timescale 1ns/1ps
  3. module vlg_design(
  4. input i_clk,
  5. input i_rest_n,
  6. output o_ds,
  7. output o_shcp,
  8. output o_stcp
  9. );
  10. //parameter i_data = 32'h12345678;
  11. wire [15:0]w_data_seg_sel;
  12. wire w_clk_12r5m;
  13. wire w_clk_1khz;
  14. wire[32:0] w_data;
  15. vio_0 your_instance_name (
  16. .clk(i_clk), // input wire clk
  17. .probe_out0(w_data) // output wire [31 : 0] probe_out0
  18. );
  19. //
  20. vlg_74hc595_v vlg_74hc595_v_inst(
  21. .i_clk(i_clk),
  22. .i_rest_n(i_rest_n),
  23. .i_data(w_data_seg_sel),
  24. .o_ds(o_ds),
  25. .o_shcp(o_shcp),
  26. .o_stcp(o_stcp)
  27. );
  28. //
  29. vlg_data_generate vlg_data_generate_inst(
  30. .i_clk(i_clk),
  31. .i_rest_n(i_rest_n),
  32. .i_clk_1khz(w_clk_1khz),
  33. .i_data(w_data),
  34. .o_data_seg_sel(w_data_seg_sel)
  35. );
  36. //
  37. vlg_div vlg_div_inst(
  38. .i_clk(i_clk),
  39. .i_rest_n(i_rest_n),
  40. .o_clk_12r5m(w_clk_12r5m),
  41. .o_clk_1khz(w_clk_1khz)
  42. );
  43. endmodule

xdc

  1. set_property PACKAGE_PIN Y18 [get_ports i_clk]
  2. set_property PACKAGE_PIN F15 [get_ports i_rest_n]
  3. set_property IOSTANDARD LVCMOS33 [get_ports i_clk]
  4. set_property IOSTANDARD LVCMOS33 [get_ports i_rest_n]
  5. set_property IOSTANDARD LVCMOS33 [get_ports o_ds]
  6. set_property IOSTANDARD LVCMOS33 [get_ports o_shcp]
  7. set_property IOSTANDARD LVCMOS33 [get_ports o_stcp]
  8. set_property PACKAGE_PIN M18 [get_ports o_ds]
  9. set_property PACKAGE_PIN F4 [get_ports o_shcp]
  10. set_property PACKAGE_PIN C2 [get_ports o_stcp]

测试结果

3,调试记录

2023年12月30日

问题:本想显示全1的,结果成这样

2023年12月31日

解决了,撸了一遍视频,找到原因是时钟频率的问题,我直接把数据传输的时钟用的 50M。应该是74HC595 不支持这么高。现在换成12.5M 正常了。

2024年1月2日星期二

  1. 完成使用vio 实现vivado自动配置数码管显示

readme

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

闽ICP备14008679号