学fpga(流水灯)

学fpga(流水灯),第1张

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        从学习方法上说,fpga的学习方面和linux c开发有点相似。

fpgalinux
语言verilog,vhdlc,c++
开发工具vivado,quartusgcc,g++
调试工具chip scope,signal tapgdb
仿真modelsimx86 linux虚拟机
运行fpga开发板arm linux开发板

        通过上面的表格,可以看出来,不管是哪一种开发方法,都需要对应的语言、开发工具、调试工具、仿真平台和实际验证环境,这些都是少不了的。只不过,fpga侧重的是并发流水线,软件倡导的是顺序执行而已。

        前面,我们讨论过计数器,也就是说从复位开始,计数器就会不停地计数下去。这么一直计数下去其实也是可以的,只要有这么一个需求就可以,或者只是想看一下计数器是不是真的会这么走下去。真实场景下面,更多的是用计数器来做一个定时器。比如,复位之后,计数器从0开始,等到计数到99的时候,就会恢复到0。这样一来,就好像有这么一个100的计数器,它会周期性的重新计数。设想一下,如果这个周期拓展到1s,那么其实就是一个1s的定时器了。不过,一般对fpga来说,1s的时间太长了,我们可以用wavedrom设计一个1周期为100的定时器。

{ "signal" : [
  { "name": "clk",         "wave": "p......|.." },
  { "name": "rst",     "wave": "010....|.." },
  { "name": "cnt",     "wave": "x22345x|67", data:["0","0","1","2","3","99","0"] }
]
}

        转变成时序图就是这样的,

        所以,这个时候需要做的就是在之前的verilog代码上面添加一个判断语句,即

always@(posedge clk or posedge rst)
    if(rst)
        cnt <= 4'd0;
    else if(cnt == 4'd99)
        cnt <= 4'd0;
    else
        cnt <= cnt + 1;

         有同学也许会说,这和流水灯有什么关系。大家不要着急,关键是这里的cnt 99,完全可以用这一条件实现led的开和灭的功能。

{ "signal" : [
  { "name": "clk",         "wave": "p......|.." },
  { "name": "rst",     "wave": "010....|.." },
  { "name": "cnt",     "wave": "x22345x|67", data:["0","0","1","2","3","99","0"] },
  { "name": "led",     "wave": "x0.....|.1", },
]
}

        上面的json转换成图形,就是这样的,

         注意这里的cnt为99的时候,led就会跳转为1高电平。等到下一个99的时候再跳转为0,这样就实现了周期性熄灭的效果。写成verilog代码应该是这样的,

always @(posedge clk or posedge rst)
    if (rst)
        led <= 1'b0;
    else if(cnt == 8'd99)
        led <= ~led;

        做到这一点似乎离我们的目标越来越近。大家可以想象一下如果有4个led灯,那么应该怎么处理。是不是可以把cnt分成4部分。99的时候,只有led1灯亮;199的时候,只有led2灯亮;299的时候,只有led3亮;399的时候只有led4灯亮。

{ "signal" : [
  { "name": "clk",         "wave": "p.....|......|.." },
  { "name": "rst",     "wave": "010...|......|.." },
  { "name": "cnt",     "wave": "x2245x|6789x.|45", data:["0","0","1","2","99","100","101","102","199","200"] },
  { "name": "led0",     "wave": "x1....|.0....|..", },
  { "name": "led2",     "wave": "x0....|.1....|.0", },
  { "name": "led3",     "wave": "x0....|......|.1", },
  { "name": "led4",     "wave": "x0....|......|..", },
]
}

        转换成图形就是这样的,

        当然上面只是一种设计方法,大家可以集思广益,用自己的方法来设计出不一样的流水灯效果。流水灯固然简单,关键还是考察背后的思考过程。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/893756.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-14
下一篇 2022-05-14

发表评论

登录后才能评论

评论列表(0条)

保存