Gvim计数器模板经典练习

Gvim计数器模板之基础练习

练习1

       dout的初值为1'b0,设计当收到5个en信号后,则dout输出1个周期的高电平,如图1所示,表1为练习1的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

en

I

1

dout

O

1

表1 练习1信号列表

 图1 练习1示意图

       这是一个很基础的模型,主要是为了让大家先理解Gvim编辑器下计数器模板的基本使用方法,add_cnt在en为1时,开始加1,当计数到5时即add_cnt为4时,end_cnt为1,此时cnt被清零,同时下一个clk时刻,dout输出1'b1,图2为练习1中各个信号的波形图,图3为练习1的代码设计。大家打开Gvim编辑器输入“i”键后回车从命令模式切换到插入模式,再输入”Jsq”回车调出编辑器下的计数器模板。

​​​​​图2 练习1中各个信号的波形图

图3 练习1的代码设计

Gvim计数器模板之嵌套练习

练习2

      电子手表,会显示当前时间的秒钟值、分钟值和时钟值,假设系统时钟为50Mhz,设计输出miao_value即秒钟值, fen_value即分钟值, shi_value即时钟值,如图4所示,表2为练习2的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

miao_value

O

6

fen_value

O

6

shi_value

O

4

表2 练习2信号列表

图4 练习2示意图

      这是一个很经典的模型,选择写在这里主要是为了让大家更好地理解Gvim编辑器下计数器模板的嵌套使用方法,因为在实际工程当中,经常会涉及到计数器的嵌套,即后一个计数器用前一个计数器的结束条件end_cnt0为自己的加一条件add_cnt1,因为系统时钟为50Mhz,所以计时一秒钟需要50_000_000个clk,秒钟计数60次向分钟进位1次,分钟数60次向时钟进位1次,然后秒钟和分钟的计数周期均为60次,时钟的计数周期为12次,这里就不再画各个信号波形的时序图了,图5为练习2的代码设计。

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​

图5 练习2的代码设计

Gvim计数器模板之flag_add

练习3

       dout的初值为1'b0,设计当收到en后,dout输出6个周期的高电平,同时en每次到来都至少间隔6个时钟周期,如图6所示,表3为练习3的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

en

O

1

dout

O

1

表3 练习3信号列表

图6 练习3示意图

       这是一个很有价值的模型,在实际项目工程中,上游模块可能输出了一个使能信号en,而我们希望在使能信号en之后的多少个时钟之后再做一些操作,或者一般的情况下,当某一个信号有效的时候,计数器才进行自加一操作,通常习惯用flag_add信号名作为计数器加一条件add_cnt,实际应用中flag_add信号通常在某一个信号为真时拉高,当end_cnt到来时候拉低,用来指示一个计数器的加一条件,从而很好地控制了一个计数器何时做计数操作。

      flag_add在en为1时被拉高用来指示计数器的加一条件add_cnt,同时在end_cnt到来的时候被拉低,使得计数器停止计数,这个练习比较简单,直接就可以把flag_add信号赋值给dout用以输出即可。图7为练习3中各个信号的波形图,图8为练习3的代码设计。

 图7 练习3中各个信号的波形图

​​​​​​

图8 练习3的代码设计

Gvim计数器模板之flag_sel

练习4

      dout初值为8'h0,当收到en1后,dout输出4个周期的8'h55;当收到en2后,dout输出8个周期的8'haa,同时en1和en2不会同时到来且间隔大于10个周期,如图9所示,表4为练习4的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

en1

I

1

en2

I

1

dout

O

8

表4 练习4信号列表

图9 练习4示意图

        这同样也是一个很有价值的模型,在实际项目工程中,flag_sel用非常多的用途,比如这个练习中上游模块可能输出了多个使能信号en1,en2等等,我们需要区别en1和en2究竟是来的哪个使能信号,它既可以用来区分上游模块的不同输入信号,也可以被定义为多位宽的信号从而起到替代顺序状态机的效果,当一个状态机是顺序执行的时候,也就是说由状态1跳转到状态2,由状态2跳转到状态3,再由状态3跳转到状态4,而不是直接从状态1跳转到状态3,由状态3跳转到状态4,再由状态4跳转到状态2,类似这种毫无规则的跳转,使用多位宽的flag_sel信号完全可以替代标准三段式状态机的状态指示信号state_c。

        flag_add在en1或者en2为1时被拉高用来指示计数器的加一条件add_cnt,同时在end_cnt到来的时候被拉低,使得计数器停止计数,flag_sel用来区分是en1到来了,还是en2到来了,同时也引入了x这个信号来用以区分同一个计数器在不同状态下需要计数的长度,这个练习中flag_add和flag_sel的使用,使得Gvim下的计数器模板应用起来也更加灵活自如。可以结合图10为练习4中各个信号的波形图来试着写写这个练习的代码,其中图11为练习4的代码设计。

图10 练习4中各个信号的波形图

​​​​​​​ ​​​​​​​ ​​​​​​​

图11 练习4的代码设计

Gvim计数器模板之din_vld和dout_vld

练习5

       dout初值为8'h0,当din_vld为1时,将当前的din值赋给dout,否则dout值保持不变,当收到4个din_vld时拉高dout_vld,如图12所示,表5为练习5的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

din_vld

I

1

din

I

8

dout_vld

O

1

dout

O

8

表5 练习5信号列表

图12 练习5示意图

       din_vld和dout_vld在FPGA设计当中很关键,它通常用来指示各个不同模块之间例化信号的数据交互,一般设计都会遵循din_vld和din两个信号同步到来的原则,也就是这个练习中描述的当din_vld为1时,将当前的din值赋给本模块的某个信号,实际项目工程中,din_vld和din可能是上游模块通过FIFO、RAM送过来的,也可能是直接扔到本模块中的,当然具体问题具体分析。大家可以对比下前面练习的en使能信号,可能从上游模块输入来的使能信号只能触发本模块的某些操作或者触发本模块的状态机,但是从上游模块输入来的din_vld和din信号却可以进行本模块的连续不断地赋值操作,大家在后期学习以后再回头看这里相信会有更加深刻的感悟。

       选择写在这里主要是为了让大家慢慢建立起一种FPGA设计的经典思维:用din_vld和din两个信号作为上游模块的输入信号,本模块再收到din_vld和din进过一些处理加工后,通过输出dout_vld和dout两个信号作为下游模块的输入信号,这也是FPGA模块划分和模块设计常用的方法。

      这个练习里只需要用一个计数器去计数din_vld到来的次数,按照练习要求数到4次时,进行清零操作,end_cnt被拉高,同时下一个时刻拉高dout_vld。其中图13为练习5中各个信号的波形图,图14为练习5的代码设计。

图13 练习5中各个信号的波形图

​​​​​​​ ​​​​​​​

图14 练习5的代码设计

练习6

     dout初值为8'h0,在收到en信号后,触发进行三个阶段的动作,第一个阶段持续6个周期,dout周期输出3个周期的8'h0和3个周期的8'h11,结束第一个阶段的时刻拉高dout_vld;第二个阶段持续8个周期,dout周期输出4个周期的8'h0和4个周期的8'h22,结束第二个阶段的时刻拉高dout_vld;第三个阶段持续10个周期,dout周期输出5个周期的8'h0和5个周期的8'h33,结束第三个阶段的时刻拉高dout_vld,并再将dout置为8'h0,重新恢复之前没收到en信号的情况,同时en每次都会在三个阶段结束之后才可能再次到来,如图15所示,表6为练习6的信号列表。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

en

I

1

dout_vld

O

1

dout

O

8

表6 练习6信号列表

图15 练习6示意图

      这个练习结合上面的各个练习的思想,也算是比较复杂的一个了,大家可以试着写一写,找到一些写FPGA时序逻辑的感觉,当然这本身也是一个很好的模型,这里面涉及到了计数器嵌套,flag_add和flag_sel,en信号的接收,dout_vld和dout信号的处理等等,如果这个练习也能顺利地写出对应的Verilog程序,那么对于Gvim编辑器下计数器的模板就可以说已经大概掌握了,相比而言只是缺少后期的实战磨练,其中图7-23为练习6中各个信号的波形图,图7-24为练习6的代码设计。

       最后简单总结下,计数器设计的一般化经验:1.搞清楚这个模块整个流程是什么样的,它需要设计几个计数器来实现;2.每个计数器在具体数什么,是否需要用flag_add作为指示信号,是否有计数器嵌套的需求,什么时候开始数即add_cnt条件,什么时候数完即end_cnt条件;3.如果一个模块里是顺序执行的过程,就如同练习6收到en信号,连续做三个周期性动作,这时候可以考虑用flag_sel 做各阶段的标志信号,同时用好x,y等等产生组合逻辑,去改变不同阶段中计数器的计数周期;4.en信号一般是上游模块输出给下游模块的使能信号,用来触发下游模块状态机或者计数器等的工作;din_vld和din信号一般是上游模块输出给下游模块的赋值信号有效和赋值信号,通常两者在设计当中会同时到来,去赋值给下游模块对应的信号。

​​​​ 图16 练习6中各个信号的波形图

​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​

图17 练习6的代码设计

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值