微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 小梅哥FPGA设计思想与验证方法视频教程之数码管动态扫描设计与实现

小梅哥FPGA设计思想与验证方法视频教程之数码管动态扫描设计与实现

时间:10-02 整理:3721RD 点击:

        大家好,今天,小梅哥继续连载本人精心录制和编辑的FPGA学习系列教程——《小梅哥FPGA设计思想与验证方法视频教程》。教程充分考虑0基础朋友的实际情况,手把手带领学习者分析思路、编写代码、仿真验证、板级调试。教语法,学仿真,一步一步,直到最后设计若干较为综合的逻辑系统。

        教程以我们自主开发的芯航线FPGA学习板为实验平台,通过若干基础和综合的系统设计讲解,一步一步掌握FPGA设计与验证的思想和方法,希望了解芯航线FPGA学习板的,请点击这里:


http://z.elecfans.com/1?ck=snow

      今天是视频第十讲,主要通过讲解数码管动态扫描原理,并提取出实现的电路结构,从电路结构入手编写代码,仿真对设计进行验证,最终板级调试时,使用In system sources and probes editor调试工具设置需要显示的内容,则数码管显示对应的数值。本节课与前面课程的风格稍有不同,本节课代码不再是核心,核心是电路结构,电路结构确定后编写代码只是照图施工的过程。这也是越来越接近FPGA设计的底层思维。希望大家仔细体会。


        接下来,大家请看视频教程,由于视频中有部分网络的链接,因此上传优酷会被屏蔽,这里就直接分享在百度云盘中了。欢迎大家转载观看。(1280*720分辨率,MP4格式,用手机观看效果非常爽哦,建议大家下载了再观看)

好消息:

从此再也不需要一个一个回复才能看下载地址了


全部开源视频下载地址:

http://pan.baidu.com/s/1kUs0vkF
视频教程中配套源码下载地址:
http://pan.baidu.com/s/1qX5hz9y


觉得好的,记得回来帮忙顶个帖哦



?欢迎加入芯航线FPGA技术支持群:472607506

小梅哥

2015年9月30日星期三

芯航线电子工作室

按照梅总的思路,将案件消抖+7段数码管结合起来做一个随机数产生的小玩具,输入两个按钮,一个start,按下开始以50mhz频率计数,一个pause按钮,按下暂停计数,得到的数马马虎虎就算作随机数。
上代码,这个是顶层模块

  1. module key_hex8 (
  2.     clk,
  3.     rst_n,
  4.     key_start,
  5.     key_pause,
  6.     sel,
  7.     seg
  8. );
  9.     input clk;
  10.     input rst_n;
  11.     input key_start;
  12.     input key_pause;

  13.     output [7:0] sel;
  14.     output [6:0] seg;

  15.     wire start_key_flag;
  16.     wire pause_key_flag;
  17.     wire[31:0] disp_data;

  18.     key_filter start_key(
  19.         .Clk(clk),
  20.         .Rst_n(rst_n),
  21.         .key_in(key_start),
  22.         .key_flag(start_key_flag),
  23.         .key_state()
  24.     );

  25.     key_filter pause_key(
  26.         .Clk(clk),
  27.         .Rst_n(rst_n),
  28.         .key_in(key_pause),
  29.         .key_flag(pause_key_flag),
  30.         .key_state()
  31.     );

  32.     ctrl my_ctrl(
  33.        .clk(clk),
  34.        .rst_n(rst_n),
  35.        .key_start_flag(start_key_flag),
  36.        .key_pause_flag(pause_key_flag),
  37.        .disp_data(disp_data)
  38.     );

  39.     HXE8 my_Hxe8(
  40.         .Clk(clk),
  41.         .Rst_n(rst_n),
  42.         .En(1),
  43.         .disp_data(disp_data),
  44.         .sel(sel),
  45.         .seg(seg)
  46.     );

  47. endmodule

复制代码


这个是梅总的按键消抖模块,中文注释乱码。请梅总自己解决

  1. module key_filter(Clk,Rst_n,key_in,key_flag,key_state);

  2.         input Clk;
  3.         input Rst_n;
  4.         input key_in;
  5.        
  6.         output reg key_flag;
  7.         output reg key_state;
  8.        
  9.         localparam
  10.                 IDEL                = 4'b0001,
  11.                 FILTER0        = 4'b0010,
  12.                 DOWN                = 4'b0100,
  13.                 FILTER1         = 4'b1000;
  14.                
  15.         reg [3:0]state;
  16.         reg [19:0]cnt;
  17.         reg en_cnt;        //浣胯兘璁℃暟瀵勫瓨鍣?
  18.        
  19. //瀵瑰閮ㄨ緭鍏ョ殑寮傛淇″彿杩涜鍚屾澶勭悊
  20.         reg key_in_sa,key_in_sb;
  21.         always@(posedge Clk or negedge Rst_n)
  22.         if(!Rst_n)begin
  23.                 key_in_sa <= 1'b0;
  24.                 key_in_sb <= 1'b0;
  25.         end
  26.         else begin
  27.                 key_in_sa <= key_in;
  28.                 key_in_sb <= key_in_sa;       
  29.         end
  30.        
  31.         reg key_tmpa,key_tmpb;
  32.         wire pedge,nedge;
  33.         reg cnt_full;//璁℃暟婊℃爣蹇椾俊鍙?
  34.        
  35. //浣跨敤D瑙﹀彂鍣ㄥ瓨鍌ㄤ袱涓浉閭绘椂閽熶笂鍗囨部鏃跺閮ㄨ緭鍏ヤ俊鍙凤紙宸茬粡鍚屾鍒扮郴缁熸椂閽熷煙涓級鐨勭數骞崇姸鎬?
  36.         always@(posedge Clk or negedge Rst_n)
  37.         if(!Rst_n)begin
  38.                 key_tmpa <= 1'b0;
  39.                 key_tmpb <= 1'b0;
  40.         end
  41.         else begin
  42.                 key_tmpa <= key_in_sb;
  43.                 key_tmpb <= key_tmpa;       
  44.         end

  45. //浜х敓璺冲彉娌夸俊鍙?
  46.         assign nedge = !key_tmpa & key_tmpb;
  47.         assign pedge = key_tmpa & (!key_tmpb);
  48.        
  49.         always@(posedge Clk or negedge Rst_n)
  50.         if(!Rst_n)begin
  51.                 en_cnt <= 1'b0;
  52.                 state <= IDEL;
  53.                 key_flag <= 1'b0;
  54.                 key_state <= 1'b1;
  55.         end
  56.         else begin
  57.                 case(state)
  58.                         IDEL :
  59.                                 begin
  60.                                         key_flag <= 1'b0;
  61.                                         if(nedge)begin
  62.                                                 state <= FILTER0;
  63.                                                 en_cnt <= 1'b1;
  64.                                         end
  65.                                         else
  66.                                                 state <= IDEL;
  67.                                 end
  68.                                        
  69.                         FILTER0:
  70.                                 if(cnt_full)begin
  71.                                         key_flag <= 1'b1;
  72.                                         key_state <= 1'b0;
  73.                                         en_cnt <= 1'b0;
  74.                                         state <= DOWN;
  75.                                 end
  76.                                 else if(pedge)begin
  77.                                         state <= IDEL;
  78.                                         en_cnt <= 1'b0;
  79.                                 end
  80.                                 else
  81.                                         state <= FILTER0;
  82.                                        
  83.                         DOWN:
  84.                                 begin
  85.                                         key_flag <= 1'b0;
  86.                                         if(pedge)begin
  87.                                                 state <= FILTER1;
  88.                                                 en_cnt <= 1'b1;
  89.                                         end
  90.                                         else
  91.                                                 state <= DOWN;
  92.                                 end
  93.                        
  94.                         FILTER1:
  95.                                 if(cnt_full)begin
  96.                                         key_flag <= 1'b1;
  97.                                         key_state <= 1'b1;
  98.                                         state <= IDEL;
  99.                                 end
  100.                                 else if(nedge)begin
  101.                                         en_cnt <= 1'b0;
  102.                                         state <= DOWN;
  103.                                 end
  104.                                 else
  105.                                         state <= FILTER1;
  106.                        
  107.                         default:
  108.                                 begin
  109.                                         state <= IDEL;
  110.                                         en_cnt <= 1'b0;               
  111.                                         key_flag <= 1'b0;
  112.                                         key_state <= 1'b1;
  113.                                 end
  114.                                
  115.                 endcase       
  116.         end
  117.        

  118.        
  119.         always@(posedge Clk or negedge Rst_n)
  120.         if(!Rst_n)
  121.                 cnt <= 20'd0;
  122.         else if(en_cnt)
  123.                 cnt <= cnt + 1'b1;
  124.         else
  125.                 cnt <= 20'd0;
  126.        
  127.         always@(posedge Clk or negedge Rst_n)
  128.         if(!Rst_n)
  129.                 cnt_full <= 1'b0;
  130.         else if(cnt == 999_999)
  131.                 cnt_full <= 1'b1;
  132.         else
  133.                 cnt_full <= 1'b0;       

  134. endmodule

复制代码


这个是梅总的7段显示模块

  1. module HXE8(Clk,Rst_n,En,disp_data,sel,seg);

  2.         input Clk;        //50M
  3.         input Rst_n;
  4.         input En;        //鏁扮爜绠℃樉绀轰娇鑳斤紝1浣胯兘锛?鍏抽棴
  5.        
  6.         input [31:0]disp_data;
  7.        
  8.         output [7:0] sel;//鏁扮爜绠′綅閫夛紙閫夋嫨褰撳墠瑕佹樉绀虹殑鏁扮爜绠★級
  9.         output reg [6:0] seg;//鏁扮爜绠℃閫夛紙褰撳墠瑕佹樉绀虹殑鍐呭锛?
  10.        
  11.         reg [14:0]divider_cnt;//25000-1
  12.        
  13.         reg clk_1K;
  14.         reg [7:0]sel_r;
  15.        
  16.         reg [3:0]data_tmp;//鏁版嵁缂撳瓨

  17. //        鍒嗛璁℃暟鍣ㄨ鏁版ā鍧?
  18.         always@(posedge Clk or negedge Rst_n)
  19.         if(!Rst_n)
  20.                 divider_cnt <= 15'd0;
  21.         else if(!En)
  22.                 divider_cnt <= 15'd0;
  23.         else if(divider_cnt == 24999)
  24.                 divider_cnt <= 15'd0;
  25.         else
  26.                 divider_cnt <= divider_cnt + 1'b1;

  27. //1K鎵弿鏃堕挓鐢熸垚妯″潡               
  28.         always@(posedge Clk or negedge Rst_n)
  29.         if(!Rst_n)
  30.                 clk_1K <= 1'b0;
  31.         else if(divider_cnt == 24999)
  32.                 clk_1K <= ~clk_1K;
  33.         else
  34.                 clk_1K <= clk_1K;
  35.                
  36. //8浣嶅惊鐜Щ浣嶅瘎瀛樺櫒
  37.         always@(posedge clk_1K or negedge Rst_n)
  38.         if(!Rst_n)
  39.                 sel_r <= 8'b0000_0001;
  40.         else if(sel_r == 8'b1000_0000)
  41.                 sel_r <= 8'b0000_0001;
  42.         else
  43.                 sel_r <=  sel_r << 1;
  44.                
  45.         always@(*)
  46.                 case(sel_r)
  47.                         8'b0000_0001:data_tmp = disp_data[3:0];
  48.                         8'b0000_0010:data_tmp = disp_data[7:4];
  49.                         8'b0000_0100:data_tmp = disp_data[11:8];
  50.                         8'b0000_1000:data_tmp = disp_data[15:12];
  51.                         8'b0001_0000:data_tmp = disp_data[19:16];
  52.                         8'b0010_0000:data_tmp = disp_data[23:20];
  53.                         8'b0100_0000:data_tmp = disp_data[27:24];
  54.                         8'b1000_0000:data_tmp = disp_data[31:28];
  55.                         default:data_tmp = 4'b0000;
  56.                 endcase
  57.                
  58.         always@(*)
  59.                 case(data_tmp)
  60.                         4'h0:seg = 7'b1000000;
  61.                         4'h1:seg = 7'b1111001;
  62.                         4'h2:seg = 7'b0100100;
  63.                         4'h3:seg = 7'b0110000;
  64.                         4'h4:seg = 7'b0011001;
  65.                         4'h5:seg = 7'b0010010;
  66.                         4'h6:seg = 7'b0000010;
  67.                         4'h7:seg = 7'b1111000;
  68.                         4'h8:seg = 7'b0000000;
  69.                         4'h9:seg = 7'b0010000;
  70.                         4'ha:seg = 7'b0001000;
  71.                         4'hb:seg = 7'b0000011;
  72.                         4'hc:seg = 7'b1000110;
  73.                         4'hd:seg = 7'b0100001;
  74.                         4'he:seg = 7'b0000110;
  75.                         4'hf:seg = 7'b0001110;
  76.                 endcase
  77.                
  78.         assign sel = (En)?sel_r:8'b0000_0000;

  79. endmodule

复制代码


这个是我写的控制模块

  1. module ctrl(
  2.     clk,
  3.     rst_n,
  4.     key_start_flag,
  5.     key_pause_flag,
  6.     disp_data
  7. );

  8.     input clk;
  9.     input rst_n;
  10.     input key_start_flag;
  11.     input key_pause_flag;

  12.     output[31:0] disp_data;

  13.     reg pause;//0计数,1停止
  14.     always  @(posedge clk or negedge rst_n)begin
  15.         if(rst_n==1'b0)begin
  16.             pause <= 1'b1;
  17.         end
  18.         else begin
  19.             if( key_start_flag ) pause <= 1'b0;
  20.             else if( key_pause_flag ) pause <= 1'b1;
  21.             else ;
  22.         end
  23.     end

  24.     reg[31:0] cnt;
  25.     always  @(posedge clk or negedge rst_n)begin
  26.         if(rst_n==1'b0)begin
  27.             cnt <= 0;
  28.         end
  29.         else begin
  30.             if( ~pause )  cnt <= cnt + 1'd1;
  31.             else ;
  32.         end
  33.     end

  34.     assign disp_data = cnt;


  35. endmodule

复制代码

节下来是testbench

  1. `timescale 1 ns/1 ns

  2. module key_hex8_tb();

  3. //时钟和复位
  4. reg clk  ;
  5. reg rst_n;

  6. //uut的输入信号
  7. reg       key_start;
  8. reg       key_pause;
  9. //uut的输出信号
  10. wire [7:0] sel;
  11. wire [6:0] seg;

  12. //时钟周期,单位为ns,可在此修改时钟周期。
  13. parameter CYCLE    = 20;

  14. //复位时间,此时表示复位3个时钟周期的时间。
  15. parameter RST_TIME = 3 ;

  16. //待测试的模块例化
  17. key_hex8 my_key_hex8(
  18.     .clk(clk),
  19.     .rst_n(rst_n),
  20.     .key_start(key_start),
  21.     .key_pause(key_pause),
  22.     .sel(sel),
  23.     .seg(seg)
  24. );


  25. //生成本地时钟50M
  26. initial begin
  27.     clk = 0;
  28.     forever
  29.         #(CYCLE/2)
  30.         clk=~clk;
  31. end

  32. //产生复位信号
  33. initial begin
  34.     rst_n = 1;
  35.     #2;
  36.     rst_n = 0;
  37.     #(CYCLE*RST_TIME);
  38.     rst_n = 1;
  39. end


  40. reg[9:0] my_rand;
  41. //输入信号赋值
  42. initial begin
  43.     #1;
  44.     //赋初值
  45.     key_start = 1;
  46.     key_pause = 1;
  47.     #(10*CYCLE);
  48.     //开始赋值
  49.     repeat(5) begin
  50.         key_start_jetter;
  51.         my_rand = {$random}%1024;
  52.         #(my_rand*CYCLE);
  53.         key_pause_jetter;
  54.     end
  55.     $stop;
  56. end



  57. task key_start_jetter;
  58.     begin
  59.         repeat(50) begin
  60.             my_rand = {$random}%1024;
  61.             #(my_rand*CYCLE) key_start = ~key_start;
  62.         end
  63.         key_start = 0;
  64.         #(2_000_000*CYCLE);
  65.         repeat(50) begin
  66.          my_rand = {$random}%1024;
  67.             #(my_rand*CYCLE) key_start = ~key_start;
  68.         end
  69.         key_start = 1;
  70.         #(2_000_000*CYCLE);
  71.     end
  72. endtask


  73. task key_pause_jetter;
  74.     begin
  75.         repeat(50) begin
  76.             my_rand = {$random}%1024;
  77.             #(my_rand*CYCLE) key_pause = ~key_pause;
  78.         end
  79.         key_pause = 0;
  80.         #(2_000_000*CYCLE);
  81.         repeat(50) begin
  82.          my_rand = {$random}%1024;
  83.             #(my_rand*CYCLE) key_pause = ~key_pause;
  84.         end
  85.         key_pause = 1;
  86.         #(2_000_000*CYCLE);
  87.     end
  88. endtask


  89. endmodule

复制代码

最后从多个角度看波形结果:

1.总图


2.第一次按下开始计数


3.第一次按下暂停计数


4.第二次按下开始计数


顶,小梅哥,讲的不错,看了你的视频,很感谢

谢谢鼓励和支持

谢谢梅哥{:1:

支持!感觉小梅哥讲的视频把老师一学期讲的课给概括了!点赞!

持续关注小梅哥的视频中。

小梅哥FPGA设计思想与验证方法视频教程

好好好好好好好好好好好好好好好好好好好好

小梅哥FPGA设计思想与验证方法视频教程之高性能计数器IP核使用

好的学习方法,好的视频。

非常感谢!想学习一下

很好 以后就用它来学习了

阿迪王大伟大伟啊我日好噶1

谢谢分享!谢谢分享!谢谢分享!谢谢分享!

棒棒的,大力支持

谢谢分享!十分感谢

好。。

谢谢小编分享,

謝謝分享......

                  学习

把小梅哥的视频都保存了

谢谢小美哥的东西分享

小梅哥FPGA设计思想与验证方法视频教程

谢谢,学习一下~~~~~~~~~~

支持。。

支持!感觉小梅哥讲的视频把老师一学期讲的课给概括了!点赞!

支持!感觉小梅哥讲的视频把老师一学期讲的课给概括了!点赞!

谢谢分享。

继续学习第十弹

小梅哥讲得不错哦。

顶,小梅哥,讲的不错

挺好的视频,看看啊

謝謝分享......

跟着小梅哥学FPGA

学习ing。

支持支持~~~请继续加油

持续关注小梅哥的视频中。

小编好人,小编真棒 真棒真棒真棒真棒真棒

接下来,大家请看视频教程,由于视

一直在看小梅哥的视频,很详细,从中能学到不少东西

这几天持续学习中

11111111111111111111111111111111111111111111111111111111111111

顶,很感谢,很好的视频

谢谢分享,希望能学到更多知识

,不错期待后续视频

不错期待后续视频;请问小梅哥有没有usb,以太网这样的教程呢

谢谢~~~~~~~~~~~~~~

支持小梅哥的教程

看看了....

bucoo    bucuo   学习  虚席

谢谢分享,希望能学到更多知识

谢谢小梅哥的分享,连载视频给了我很大的帮助,我一定会学好FPGA的。

持续关注小梅哥的视频中。

我下了次序有点乱

讲的不错,继续下载

用这个练习不错,尤其是testbench写得佷威武

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top