查看: 431|回复: 3

[原创] 从零开始学FPGA我的第七个实验(记录一下)

[复制链接]

19

主题

2

好友

370

积分

秀才

Rank: 3Rank: 3

  • TA的每日心情
    开心
    2016-9-21 20:33
  • 签到天数: 29 天

    [LV.4]偶尔看看III

    发表于 2016-7-24 23:18:54 |显示全部楼层
    从零开始学FPGA我的第七个实验(记录一下)
    第七个实验是编写数码管的驱动
    驱动数码管动态扫描显示,驱动的模型是:
    模型.jpg

    实际上使用了一个六选一的数据选择器输入的数据是24位的,分成了【3:0】【7:4】【11:8】【15:12】【19:16】【23:20】分成了6个数据长度为4的数据。
    左下角的是分频器也就是计数器,将50MHZ的时钟分频成为1KHZ的时钟周期为1ms的时钟信号 50MHZ-----一个周期是20ns 1KHZ半个周期是0.5ms=500000ns所以计数器的计数值是500000/20=25000(为什么是用半个周期除以系统时钟周期呢?自己的理解是因为计数是沿边沿计数的)1ms产生移位欺骗人眼的时间要小于20ms
    下面是代码:
    1. module SMG(Clk,Rst_n,En,data,sel,seg);


    2. input Clk;
    3. input Rst_n;
    4. input En;

    5. input [23:0]data;

    6. output [5:0] sel;//数码管的位选
    7. output reg [6:0] seg;//数码管的段选(要显示的内容)

    8. reg [14:0] div_cnt;//25000-1=24999
    9. reg clk_1k;
    10. reg [5:0]sel_r;
    11. reg [3:0]data_tmp;//数据缓存
    12. //计数器从0计数到24999       
    13. always @(posedge Clk or negedge Rst_n)
    14. if(!Rst_n)
    15. div_cnt <=15'd0;
    16. else if (!En)
    17. div_cnt <=15'd0;
    18. else if(div_cnt == 24999)
    19. div_cnt <= 15'd0;
    20. else
    21. div_cnt = div_cnt + 1'b1;
    22. //但计数满了24999的时候clk_1k翻转一次产生1khz的clk 时钟信号
    23. always @(posedge Clk or negedge Rst_n)
    24. if(!Rst_n)
    25. clk_1k <= 1'b0;
    26. else if (div_cnt == 24999)
    27. clk_1k <= ~clk_1k;
    28. else
    29. clk_1k <= clk_1k;

    30. //循环移位的寄存器
    31. always@(posedge clk_1k or negedge Rst_n)
    32. if(!Rst_n)
    33. sel_r <= 6'b00_0001;
    34. else if(sel_r == 6'b10_0000)
    35. sel_r <= 6'b00_0001;
    36. else
    37. sel_r <= sel_r << 1;
    38. //选择显示数据       
    39. always @(*)
    40. case (sel_r)
    41. 6'b00_0001: data_tmp = data[3:0];
    42. 6'b00_0010: data_tmp = data[7:4];
    43. 6'b00_0100: data_tmp = data[11:8];
    44. 6'b00_1000: data_tmp = data[15:12];
    45. 6'b01_0000: data_tmp = data[19:16];
    46. 6'b10_0000: data_tmp = data[23:20];
    47. default :data_tmp =4'b0000;
    48. endcase
    49. //查表显示0到f的数据       
    50. always@(*)
    51. case(data_tmp)//查表
    52. 4'h0:seg = 7'b1000000;
    53. 4'h1:seg = 7'b1111001;
    54. 4'h2:seg = 7'b0100100;
    55. 4'h3:seg = 7'b0110000;
    56. 4'h4:seg = 7'b0011001;
    57. 4'h5:seg = 7'b0010010;
    58. 4'h6:seg = 7'b0000010;
    59. 4'h7:seg = 7'b1111000;
    60. 4'h8:seg = 7'b0000000;
    61. 4'h9:seg = 7'b0010000;
    62. 4'ha:seg = 7'b0001000;
    63. 4'hb:seg = 7'b0000011;
    64. 4'hc:seg = 7'b1000110;
    65. 4'hd:seg = 7'b0100001;
    66. 4'he:seg = 7'b0000110;
    67. 4'hf:seg = 7'b0001110;
    68. endcase
    69. //        位选的实现       
    70. assign sel =(En)? sel_r:6'b00_0000;
    71. endmodule
    复制代码
    测试代码 testbench:
    1. `timescale 1ns/1ns
    2. `define clk_period 20
    3. //20ns = 50mhz
    4. module SMG_tb;

    5. reg Clk;
    6. reg Rst_n;
    7. reg En;

    8. reg [23:0] data;

    9. wire [5:0]sel;//位选
    10. wire [6:0]seg;//段选





    11. SMG SMG0(
    12. .Clk(Clk),
    13. .Rst_n(Rst_n),
    14. .En(En),
    15. .data(data),
    16. .sel(sel),
    17. .seg(seg)
    18. );
    19. initial Clk = 1;
    20. always #(`clk_period/2) Clk = ~Clk;

    21. initial begin
    22. Rst_n = 1'b0;
    23. En = 1;
    24. data = 24'h123456;
    25. #(`clk_period *30);
    26. Rst_n =1;
    27. #20000000;
    28. data =24'h201607;
    29. #20000000;
    30. data =24'h202009;
    31. #20000000;
    32. $stop;
    33. end

    34. endmodule
    复制代码
    rtl仿真:
    rtl.png

    符合编码

    门级仿真:
    门级.png



    待续。。。



    回复

    使用道具 举报

    19

    主题

    2

    好友

    370

    积分

    秀才

    Rank: 3Rank: 3

  • TA的每日心情
    开心
    2016-9-21 20:33
  • 签到天数: 29 天

    [LV.4]偶尔看看III

    发表于 2016-7-24 23:19:35 |显示全部楼层
        占楼     
    回复

    使用道具 举报

    15

    主题

    0

    好友

    500

    积分

    举人

    Rank: 4

  • TA的每日心情
    奋斗
    2016-7-12 22:55
  • 签到天数: 13 天

    [LV.3]偶尔看看II

    发表于 2016-7-24 23:31:46 |显示全部楼层
    写得不错,veriog 语言很规范,条理清晰
    回复

    使用道具 举报

    15

    主题

    0

    好友

    500

    积分

    举人

    Rank: 4

  • TA的每日心情
    奋斗
    2016-7-12 22:55
  • 签到天数: 13 天

    [LV.3]偶尔看看II

    发表于 2016-7-24 23:32:41 |显示全部楼层
    always @(posedge Clk or negedge Rst_n)
    if(!Rst_n)
    clk_1k <= 1'b0;
    else if (div_cnt == 24999)
    clk_1k <= ~clk_1k;
    else
    clk_1k <= clk_1k;
    这个分频时钟写得很好的
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /6 下一条


    手机版|爱板网 |网站地图  

    GMT+8, 2016-12-7 00:04 , Processed in 0.200236 second(s), 13 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部