我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1338|回复: 13

[资料贡献] 手把手教你学FPGA设计-秒表功能

[复制链接]

该用户从未签到

126

主题

239

回帖

0

积分

二级逆天

积分
0

终身成就奖金点子奖原创先锋奖

发表于 2020-5-13 17:36:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、项目背景同上一个项目。
二、设计目标开发板或者模块是有 8 位数码管,本次设计需要使用1个数码管,即数码管0,实现类似于秒表的功能,具体要求如下:
复位后,数码管0显示数字0并持续1秒;然后显示数字1并持续2秒;然后显示数字2并持续3秒;以此类推,最后是显示数字9并持续10秒。然后再次循环
上板效果图如下图所示。
   
上板的演示效果,请登陆网址查看:www.mdy-edu.com/xxxx
三、模块设计我们要实现的功能,概括起来就是控制8个数码管,其中数码管0亮,其他数码管不亮。并让数码管0显示不同的数字。
要控制8个数码管,就需要控制位选信号,即FPGA要输出一个8位的位选信号,设为seg_sel,其中seg_sel[0]对应数码管0,seg_sel[1]对应数码管1,以此类推,seg_sel[7]对应数码管7。
要显示不同的数字,就需要控制段选信号,不需要用到DP,一共有7根线,即FPGA要输出一个7位的段选信号,设为seg_ment,seg_ment[6]~segm_ment[0]分别对应数码管的abcdefg(注意对应顺序)。
我们还需要时钟信号和复位信号来进行工程控制。
综上所述,我们这个工程需要4个信号,时钟clk,复位rst_n,输出的位选信号seg_sel和输出的段选信号seg_ment。
信号线
信号线
FPGA管脚
内部信号
SEG_E
SEG0
Y6
seg_ment[2]
SEG_DP
SEG1
W6
未用到
SEG_G
SEG2
Y7
seg_ment[0]
SEG_F
SEG3
W7
seg_ment[1]
SEG_D
SEG4
P3
seg_ment[3]
SEG_C
SEG5
P4
seg_ment[4]
SEG_B
SEG6
R5
seg_ment[5]
SEG_A
SEG7
T3
seg_ment[6]
DIG1
DIG_EN1
T4
seg_sel[0]
DIG2
DIG_EN2
V4
seg_sel[1]
DIG3
DIG_EN3
V3
seg_sel[2]
DIG4
DIG_EN4
Y3
seg_sel[3]
DIG5
DIG_EN5
Y8
seg_sel[4]
DIG6
DIG_EN6
W8
seg_sel[5]
DIG7
DIG_EN7
W10
seg_sel[6]
DIG8
DIG_EN8
Y10
seg_sel[7]


我们先分析要实现的功能,数码管0显示数字0,翻译成信号就是seg_sel的值为8’b1111_1110,seg_ment的值为7’b000_0001。然后数码管0显示数字1,也就是说seg_sel的值为8’b1111_1110,seg_ment的值为7’b100_1111。以此类推,数码管0显示数字9,就是seg_sel的值为8’b1111_1110,seg_ment的值为7’b000_0100。


seg_sel一直为8’hfe,不变化。seg_ment隔一段时间后会变化,而这个时间在不同时期还不相同。把时间信息补充上,得到下面的波形示意图。

          上图就是seg_sel和seg_seg信号的变化波形图。在显示第1个时,seg_sel=8’hfe,seg_ment=7’h01并持续1秒;在第2个时,seg_sel=8’hfe,seg_ment=7’h4f并持续2秒;以此类推,第8个时,seg_sel=8’hfe,seg_ment=7’h04并持续10秒。然后又再次重复。
由波形图可知,我们需要1个计数器用来计算时间,如2秒、3秒等。另外,我们还需要一个计数器,用来计算在第几个阶段中。所以总共需要2个计数器。
本工程的工作时钟是50MHz,即周期为20ns,计数器计数到2_000_000_000/20=100_000_000个,我们就能知道2秒时间到了。以类类推,在第2次时,数到150_000_000个,就知道了3秒时间到。第9次时,数到500_000_000个,就表示10秒时间到。另外,由于该计数器是不停地计数,永远不停止的,可以认为加1条件一直有效,可写成:assignadd_cnt0==1。综上所述,结合变量法,该计数器的代码如下


1
2
3
4
5
6
7
8
9
10
11
12
13
14
always @(posedge clk or negedge rst_n)begin
    IF(!rst_n)begin
        cnt0 <= 0;
    end
    else if(add_cnt0)begin
        if(end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1;
    end
end

assign add_cnt0 = 1 ;
assign end_cnt0 = add_cnt0 && cnt0== x-1 ;

第二个计数器用于表示第几个,很自然可以看到,每个阶段完成后,该计数器加1,因此加1条件可为end_cnt0。该计数器一共要数10次。所以代码为:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt1 <= 0;
    end
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
end

assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1== 10-1 ;

接下来设计seg_sel。该信号一直为8’hfe,所以代码直接写成如下:


1
assign seg_sel = 8'hfe ;

我们来思考输出信号seg_ment的变化。概括起来,在第1次的时候输出值为7’h01;在第2次的时候输出值为7’h4f;以此类推,在第8次的时候输出值为7’h0f。我们用信号cnt1来代替第几次,也就是:当cnt1==0的时候,输出值为7’h01;在cnt1==1的时候输出值为7’h4f;以此类推,在cnt1==9的时候输出值为7’h04。再进一步翻译成代码,就变成如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        seg_ment <= 7'h01;
    end
    else if(cnt1==0)begin
        seg_ment <= 7'h01;
    end
    else if(cnt1==1)begin
        seg_ment <= 7'h4f;
    end
    else if(cnt1==2)begin
        seg_ment <= 7'h12;
    end
    else if(cnt1==3)begin
        seg_ment <= 7'h06;
    end
    else if(cnt1==4)begin
        seg_ment <= 7'h4c;
    end
    else if(cnt1==5)begin
        seg_ment <= 7'h24;
    end
    else if(cnt1==6)begin
        seg_ment <= 7'h20;
    end
    else if(cnt1==7)begin
        seg_ment <= 7'h0f;
    end
    else if(cnt1==8)begin
        seg_ment <= 7'h00;
    end
    else if(cnt1==9)begin
        seg_ment <= 7'h04;
    end
end
然后,用组合逻辑把x的值确定下来。




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
always  @(*)begin
    if(cnt1==0)begin
        x = 50_000_000;
    end
    else if(cnt1==1)begin
        x = 100_000_000;
    end
    else if(cnt1==2)begin
        x = 150_000_000;
    end
    else if(cnt1==3)begin
        x = 200_000_000;
    end
    else if(cnt1==4)begin
        x = 250_000_000;
    end
    else if(cnt1==5)begin
        x = 300_000_000;
    end
    else if(cnt1==6)begin
        x = 350_000_000;
    end
    else if(cnt1==7)begin
        x = 400_000_000;
    end
    else if(cnt1==8)begin
        x = 450_000_000;
    end
    else if(cnt1==9)begin
        x = 500_000_000;
    end
end

此次,主体程序已经完成。接下来是将module补充完整。
将module的名称定义为my_time。并且我们已经知道该模块有4个信号:clk、rst_n、seg_sel和seg_ment,代码如下:


1
2
3
4
5
6
module my_time(
    clk    ,
    rst_n  ,
    seg_sel,
    seg_ment
    );


其中clk、rst_n是1位的输入信号,seg_sel是8位的输出信号,seg_ment是7位的输出信号,根据此,补充输入输出端口定义。代码如下:


1
2
3
4
input           clk       ;
input           rst_n     ;
output   [7:0]  seg_sel   ;
output   [6:0]  seg_ment  ;


接下来定义信号类型。
cnt0是用always产生的信号,因此类型为reg。cnt0计数的最大值为500_000_000,需要用29根线表示,即位宽是29位。add_cnt0和end_cnt0都是用assign方式设计的,因此类型为wire。并且其值是0或者1,1个线表示即可。因此代码如下:


1
2
3
reg    [28:0]            cnt0        ;
wire                     add_cnt0    ;
wire                     end_cnt0    ;

cnt1是用always产生的信号,因此类型为reg。cnt1计数的最大值为9,需要用4根线表示,即位宽是4位。add_cnt1和end_cnt1都是用assign方式设计的,因此类型为wire。并且其值是0或者1,1根线表示即可。因此代码如下:


1
2
3
reg    [3:0]            cnt1        ;
wire                     add_cnt1    ;
wire                     end_cnt1    ;

seg_sel是用assign方式设计的,因此类型为wire,其一共有8根线,即位宽为8。因此代码如下:


1
wire    [7:0]  seg_sel   ;

seg_ ment是用always方式设计的,因此类型为reg,其一共有7根线,即位宽为7。因此代码如下:


1
reg   [6:0]  seg_ment   ;
x是用always方式设计的,因此类型为reg,他的位数和cnt0是一致的。


1
reg   [28:0]  x   ;

至此,整个代码的设计工作已经完成。整体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93


module miaobiao(
    clk    ,
    rst_n  ,
    seg_sel,
    seg_ment
    );



    input               clk    ;
    input               rst_n  ;


    output    [7:0]  seg_sel   ;
    output   [6:0]  seg_ment   ;


    reg           [28:0]      cnt0;
    reg           [3:0]       cnt1;
    wire      add_cnt0;
    wire      end_cnt0;
    wire      add_cnt1;
    wire      end_cnt1;
    wire    [7:0]  seg_sel   ;
    reg   [6:0]  seg_ment   ;

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt0 <= 0;
        end
        else if(add_cnt0)begin
            if(end_cnt0)
                cnt0 <= 0;
            else
                cnt0 <= cnt0 + 1;
        end
    end

    assign add_cnt0 = 1;
    assign end_cnt0 = add_cnt0 && cnt0== 50000000-1;

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt1 <= 0;
        end
        else if(add_cnt1)begin
            if(end_cnt1)
                cnt1 <= 0;
            else
                cnt1 <= cnt1 + 1;
        end
    end

    assign add_cnt1 = end_cnt0;
    assign end_cnt1 = add_cnt1 && cnt1==10-1 ;
    assign seg_sel  = 8'hfe;
  always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        seg_ment <= 7'h01;
    end
    else if(cnt1==0)begin
        seg_ment <= 7'h01;
    end
    else if(cnt1==1)begin
        seg_ment <= 7'h4f;
    end
    else if(cnt1==2)begin
        seg_ment <= 7'h12;
    end
    else if(cnt1==3)begin
        seg_ment <= 7'h06;
    end
    else if(cnt1==4)begin
        seg_ment <= 7'h4c;
    end
    else if(cnt1==5)begin
        seg_ment <= 7'h24;
    end
    else if(cnt1==6)begin
        seg_ment <= 7'h20;
    end
    else if(cnt1==7)begin
        seg_ment <= 7'h0f;
    end
    else if(cnt1==8)begin
        seg_ment <= 7'h00;
    end
    else if(cnt1==9)begin
        seg_ment <= 7'h04;
    end
end
always  @(*)begin
    if(cnt1==0)begin
        x = 50_000_000;
    end
    else if(cnt1==1)begin
        x = 100_000_000;
    end
    else if(cnt1==2)begin
        x = 150_000_000;
    end
    else if(cnt1==3)begin
        x = 200_000_000;
    end
    else if(cnt1==4)begin
        x = 250_000_000;
    end
    else if(cnt1==5)begin
        x = 300_000_000;
    end
    else if(cnt1==6)begin
        x = 350_000_000;
    end
    else if(cnt1==7)begin
        x = 400_000_000;
    end
    else if(cnt1==8)begin
        x = 450_000_000;
    end
    else if(cnt1==9)begin
        x = 500_000_000;
    end
end
  endmodule

下一步是新建工程和上板查看现象。
四、综合工程和上板新建工程首先在d盘中创建名为“miaobiao”的工程文件夹,将写的代码命名为“miaobiao.v”,顶层模块名为“miaobiao”。





然后打开Quartus Ⅱ,点击File下拉列表中的New Project Wzard...新建工程选项。


3.再出现的界面中直接点击Next。




4.之后出现的是工程文件夹、工程名、顶层模块名设置界面。按照之前的命名进行填写,第一栏选择工程文件夹“miaobiao”,第二栏选择工程文件“miaobiao”,最后一栏选择顶层模块名“miaobiao”,然后点击”Next”,在出现的界面选择emptyproject。




5.之后是文件添加界面。添加之前写的“miaobian.v”文件,点击右侧的“Add”按钮,之后文件还会出现在大方框里,之后点击“Next”。


器件型号选择界面。选择Cyclone ⅣE,在芯片型号选择处选择EP4CE15F23C8,然后点击“Next”。



EDA工具界面。直接点击“Next”。


8.之后出现的界面是我们前面设置的总结,确认无误后点击“Finish”。




综合1.新建工程步骤完成后,就会出现以下界面。在“Project Navigator”下选中要编译的文件,点击上方工具栏中“StartCompilation”编译按钮(蓝色三角形)。


2.编译成功后会出现一下界面。


配置管脚1.点击箭头所指的管脚配置按钮“Pin Planner”,进入管脚配置界面。


2.在下图location处双击填上对应的管脚号,管脚号可参照整体代码下方的管脚配置,回车即可。



管脚配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1

set_location_assignment PIN_G1 -to clk
set_location_assignment PIN_AB12 -to rst_n
set_location_assignment PIN_T3 -to seg_ment[6]
set_location_assignment PIN_R5 -to seg_ment[5]
set_location_assignment PIN_P4 -to seg_ment[4]
set_location_assignment PIN_P3 -to seg_ment[3]
set_location_assignment PIN_Y6 -to seg_ment[2]
set_location_assignment PIN_W7 -to seg_ment[1]
set_location_assignment PIN_Y7 -to seg_ment[0]
set_location_assignment PIN_Y10 -to seg_sel[7]
set_location_assignment PIN_W10 -to seg_sel[6]
set_location_assignment PIN_W8 -to seg_sel[5]
set_location_assignment PIN_Y8 -to seg_sel[4]
set_location_assignment PIN_Y3 -to seg_sel[3]
set_location_assignment PIN_V3 -to seg_sel[2]
set_location_assignment PIN_V4 -to seg_sel[1]
set_location_assignment PIN_T4 -to seg_sel[0]

布局布线管脚配置完成后,在进行一次编译。
连接开发板图中,下载器接入电脑USB接口,电源接入电源,然后摁下蓝色开关。


上板1.双击Tasks一栏中”Program Device”。


2.会出现如下界面,点击add file添加.sof文件,点击“Start”,会在“Progress”出显示进度。


3.进度条中提示成功后,即可在开发板上观察到相应的现象。[sub][/sub][sup][/sup][strike][/strike]
回复

使用道具 举报

该用户从未签到

12

主题

7221

回帖

100

积分

游客

积分
100

终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

QQ
发表于 2020-5-13 18:54:03 | 显示全部楼层
回复

使用道具 举报

  • TA的每日心情
    开心
    2024-9-7 09:00
  • 签到天数: 2 天

    [LV.1]初来乍到

    0

    主题

    4981

    回帖

    3456

    积分

    二级逆天

    积分
    3456

    终身成就奖社区居民优秀斑竹奖

    QQ
    发表于 2020-5-13 20:03:33 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    7 小时前
  • 签到天数: 43 天

    [LV.5]常住居民I

    18

    主题

    918

    回帖

    886

    积分

    1元学习PADS(5期)

    积分
    886

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    发表于 2020-5-13 20:15:07 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    6218

    回帖

    8731

    积分

    二级逆天

    积分
    8731

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2020-5-16 08:42:41 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    87

    主题

    1132

    回帖

    2475

    积分

    PADS-241024高级班

    积分
    2475

    终身成就奖

    发表于 2020-5-16 08:57:01 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    9 小时前
  • 签到天数: 105 天

    [LV.6]常住居民II

    2

    主题

    7206

    回帖

    1万

    积分

    三级逆天

    积分
    10617

    终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2020-5-26 08:56:39 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    38

    主题

    395

    回帖

    1808

    积分

    PADS-241024高级班

    积分
    1808

    终身成就奖特殊贡献奖

    发表于 2020-5-26 09:38:26 | 显示全部楼层
    ~只要思想不滑坡,办法总比困难多~
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    9 小时前
  • 签到天数: 105 天

    [LV.6]常住居民II

    2

    主题

    7206

    回帖

    1万

    积分

    三级逆天

    积分
    10617

    终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2020-5-29 08:59:16 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    9 小时前
  • 签到天数: 105 天

    [LV.6]常住居民II

    2

    主题

    7206

    回帖

    1万

    积分

    三级逆天

    积分
    10617

    终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2020-6-1 08:57:38 | 显示全部楼层
    回复

    使用道具 举报

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

    本版积分规则

    公告:服务器刚移机,
    大家请不要下载东西。
    会下载失败


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    ( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

    平平安安
    TOP
    快速回复 返回顶部 返回列表