在线咨询 切换到宽版
eetop公众号 创芯大讲堂 创芯人才网

 找回密码
 注册

手机号码,快捷登录

手机号码,快捷登录

搜帖子
查看: 1688|回复: 2

[原创] FPGA设计整洁代码3-信号命名和定义应该明确

[复制链接]
发表于 2018-9-4 09:09:36 | 显示全部楼层 |阅读模式

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

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

×

在设计中,我们不断的给目录、源代码、文件、函数、变量、参数、类、封包进行命名与定义。当一件工作需要进行的次数非常之多,足以证明它是不可或缺的基本工作。我们一定要知道一点,基础工作是整个项目的基石。忽视抑或是轻视基础工作是一件非常错误的工作理念。我们需要用最严谨认真的态度去对待,同时作为回报,它将令你的作品显得专业而优雅。

我们以信号的定义为例来说明这个问题。先来看这么一组代码:

  

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

  

4344

  

45

  

464748

  
  

always @(posedge clk or negedge rst_n)begin

  

    if(!rst_n)begin

  

        cnt <= 0;

  

    end

  

    else if(add_cnt)begin

  

        if(end_cnt)

  

            cnt <= 0;

  

        else

  

            cnt <= cnt + 1;

  

    end

  

end

  


  

assign add_cnt = flag1||flag2 ;        

  

assign end_cnt = add_cnt && cnt==x-1 ;

  


  

always  @(posedge clk or negedge  rst_n)begin

  

    if(rst_n==1'b0)begin

  

        flag1 <= 1'b0;

  

    end

  

    else if(en1)begin

  

        flag1 <= 1'b1;

  

    end

  

    else if(end_cnt)begin

  

        flag1 <= 1'b0;

  

    end

  

end

  


  

always  @(posedge clk or negedge  rst_n)begin

  

    if(rst_n==1'b0)begin

  

        flag2 <= 1'b1;

  

    end

  

    else if(en2)begin

  

        flag2 <= 1'b1;

  

    end

  

    else if(end_cnt)begin

  

        flag2 <= 1'b0;

  

    end

  

end

  


  

always  @(*)begin

  

    if(flag1)

  

        x = 5;

  

    else if(flag2)

  

        x = 7;

  

    else begin

  

        x = 0;

  

    end

  

end

  


  


这组代码的功能是当en1时计数5下;en2计数7下。在这组代码中,en1时flag1拉高;end-cnt时flag1变低;en2时flag2拉高;end-cnt时flag2变低;也就是在flag1或者flag2时加一,然后用flag1和flag2分别区分计数5下和7下。

尽管能够实现功能,但是在这组代码中,存在信号定义不明确得现象。 flag1和flag2到底是什么意思?是表示flag1(flag2)时en1产生,还是en1(en2)时的计数状态?为说明这一点就得用到XXXXX (写加一条件时需要用到add_cnt = flag1||flag2)语句。

这里重申一下我们很重要的那条简单原则,一个代码(信号)只做一件事且做好这件事!按照这个规则,思路就是这样了:用一个信号flag1来表示计数状态,另外一个信号flag2表示是由en1还是en2所产生。那么,加一与否的条件非常简单,就是是否处于工作状态(flag1);同理,计数5或者7下只需要使用flag2一个信号。那么代码就会是这样:

  

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

  

3839

  

404142

  

43

  

44

  

45

  


  
  

always @(posedge clk  or negedge rst_n)begin

  

    if(!rst_n)begin

  

        cnt <= 0;

  

    end

  

    else if(add_cnt)begin

  

        if(end_cnt)

  

            cnt <= 0;

  

        else

  

            cnt <= cnt + 1;

  

    end

  

end

  


  

assign add_cnt =  flag1 ;      

  

assign end_cnt =  add_cnt && cnt==x-1 ;

  


  

always  @(posedge clk or negedge rst_n)begin

  

    if(rst_n==1'b0)begin

  

        flag1 <= 1'b0;

  

    end

  

    else if(en1||en2 )begin

  

        flag1 <= 1'b1;

  

    end

  

    else if(end_cnt)begin

  

        flag1 <= 1'b0;

  

    end

  

end

  


  

always  @(posedge clk or negedge rst_n)begin

  

    if(rst_n==1'b0)begin

  

        flag2 <= 1'b1;

  

    end

  

    else if(en1)begin

  

        flag2 <= 1'b0;

  

    end

  

    else if(en2)begin

  

        flag2 <= 1'b1;

  

    end

  

end

  


  

always  @(*)begin

  

    if(flag==0)

  

        x = 5;

  

    else

  

        x = 7;

  

end

  


  


看到这里,也许有些朋友会觉得:好像区别没那么大啊?ok,我们假设一下,如果程序中不仅是是en1,en2,而是有en3,en4……enX,又或者将来需要维护和优化,这两者的区别将会天壤之别。

关于信号定义方面,《至简设计法》的作者潘文明给出了一个近乎完美的答案。例如在计数器代码设计中的“架构八步法”,第一步就是明确定义信号,用具体、清晰且无疑异的语句,定义每个信号所要实现的功能,以及重点描述信号的变化情况。如下图中的信号列表。

信号列表。(4)(用文字版)

  

信号名

  
  


I/O

  
  

位宽

  
  

说明

  
  

clk

  
  

I

  
  

1

  
  

系统工作时钟

  
  

rst_n

  
  

I

  
  

1

  
  

系统复位信号

  
  

Din_sop

  
  

I

  
  

1

  
  

vld=1时才有效,输入报文头指示信号

  
  

Din_eop

  
  

I

  
  

1

  
  

vld=1时才有效,输入报文尾指示信号

  
  

Din_vld

  
  

I

  
  

1

  
  

输入数据有效标志,高电平有效

  
  

Din_err

  
  

I

  
  

1

  
  

输入报文错误标志,在eop有效时才有效

  
  

din

  
  

I

  
  

8

  
  

输入数据总线

  
  

Dout_sop

  
  

O

  
  

1

  
  

vld=1时才有效,输出报文头指示信号

  
  

Dout_eop

  
  

O

  
  

1

  
  

vld=1时才有效,输出报文尾指示信号

  
  

Dout_vld

  
  

O

  
  

1

  
  

输出数据有效标志,高电平有效

  
  

dout

  
  

O

  
  

8

  
  

输出数据总线

  
  

Dout_err

  
  

O

  
  

1

  
  

输出报文错误标志,在eop有效时才有效

  


从中可以看出,优秀的FPGA设计师一开始就从顶层结构明确定义信号,将可能出现的混乱从根源上解决。这样的思路和方法实在非常值得我们每一位从业者学习和借鉴。


FPGA整洁的代码3.pdf

328.05 KB, 下载次数: 11 , 下载积分: 资产 -2 信元, 下载支出 2 信元

发表于 2018-9-4 13:20:09 | 显示全部楼层
thankyou
回复 支持 反对

使用道具 举报

发表于 2018-9-4 14:54:43 | 显示全部楼层
clk_50M 会不会更加好一点!
定义寄存器最好加入注释,表明该寄存器的作用
always @(posedge clk  or negedge rst_n) 后加注释,表明当前作用
function  ,task等等都加注释
怎么感觉最好都加注释~~~~~~~~~~
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

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


手机版| 小黑屋| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-8-29 00:26 , Processed in 0.023441 second(s), 4 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表