(原创)基于FPGA的调光流水灯(Verilog,CPLD/FPGA)
1.Abstract
前几天做了一个呼吸灯,觉得确实挺有意思的;可惜的是只有一个灯管亮,板子上有四个灯,要是能让这些灯有序地亮起来,那应该更有趣味了!跟传统的一样,逻辑上做成一个流水灯的样式,这种带有PWM调光的吸引样式,真可谓是超级流水灯了。
做这个是在已做好的呼吸灯的基础上进行添加功能的,整理好了也在随笔里边,这里就直接引用出来。
基于Verilog的PWM呼吸灯:http://www.cnblogs.com/hechengfei/p/4106538.html
2.Content
2.1 总体设计
PWM的原理在呼吸灯的那部分已经整理好了,这里就省去了原理分析一部分了,把做好的作为底层的一个小模块,主要关注顶层逻辑的设计了。
要使灯顺序的流水起来,自然是一个时序逻辑,最佳的方法就是采用状态机,预先将各个状态分配好,然后让各个状态有序地切换,时序逻辑就清晰得被表达出来。板子上有4个灯,依次流水过去然后再回来,然后循环这样的逻辑;用图表示或许直观些。
FIG2.1 总体逻辑
在途中,蓝色线表示向右流水,红色线表示向左流水。一次完整的流水执行下来,如绿色箭头指示;首先是LED0表演,完毕后,转至LED1表演,完毕后,再转至LED2表演,依次下去,直至回到LED0表演。
根据上述的逻辑,将所有的逻辑状态分配出来;将总体逻辑平铺开,去掉多余的状态,就有8-2 = 6个状态(首尾的两个状态各重了一次)。分别用S0到S7八个状态表示(多余的两个状态直接转到S0),用状态表来说明一下。
表2.1 总体状态转换表
当前状态 |
转换条件 |
下一状态 |
S0 |
!RST 或者 !END0 |
S0 |
S0 |
RST&END0 |
S1 |
S1 |
!RST |
S0 |
S1 |
RST & (!END1) |
S1 |
S1 |
RST & END1 |
S2 |
S2 |
!RST |
S0 |
S2 |
RST & (!END2) |
S2 |
S2 |
RST & END2 |
S3 |
S3 |
!RST |
S0 |
S3 |
RST & (!END3) |
S3 |
S3 |
RST & END3 |
S4 |
S4 |
!RST |
S0 |
S4 |
RST & (!END2) |
S4 |
S4 |
RST & END2 |
S5 |
S5 |
!RST | END1 |
S0 |
S5 |
RST & (!END1) |
S5 |
S6 |
*(Unconditional) |
S0 |
S7 |
*(Unconditional) |
S0 |
用状态装换图表示可能更直观一些。
FIG2.2 总体状态转换图
图中,绿色部分表示正常状态转换,红色部分表示控制信号强制转换。用状态转换图的方法虽然画得比较复杂,线比较多,但更容易理解和便于编写状态机。
完成信号END的产生。在PWM呼吸灯中,它也是一个状态转换的实例,END信号的产生是由内部寄存器存储和操作的,用作子模块以后,最后的状态应该作为端口输出出来,以便顶层模块检测和顶层状态切换处理。顾只需要在原来的模块中添加一个END信号,在PWM一个周期输出完成以后,将此信号输出出来。
2.2 顶层整合
顶层的整合就是将所有模块连接起来,既可以采用Block块的方式,也可以用文本的方式。顶层块连接了控制模块和子状态控制块模块,各自逻辑描述如下。
顶层块的描述:
module breath(LED,CLK,RST);
output [3:0] LED; input CLK;
input RST; wire S_END0;
wire S_END1;
wire S_END2;
wire S_END3; wire RST_LED0;
wire RST_LED1;
wire RST_LED2;
wire RST_LED3; breath_state M0 (.RST_LED0(RST_LED0), .RST_LED1(RST_LED1), .RST_LED2(RST_LED2), .RST_LED3(RST_LED3),
.S_END0(S_END0), .S_END1(S_END1), .S_END2(S_END2), .S_END3(S_END3),
.CLK(CLK), .RST(RST)); breath_led M1 (.LED(LED[0]), .S_END(S_END0), .CLK(CLK), .RST(RST_LED0));
breath_led M2 (.LED(LED[1]), .S_END(S_END1), .CLK(CLK), .RST(RST_LED1));
breath_led M3 (.LED(LED[2]), .S_END(S_END2), .CLK(CLK), .RST(RST_LED2));
breath_led M4 (.LED(LED[3]), .S_END(S_END3), .CLK(CLK), .RST(RST_LED3)); endmodule
状态控制块的描述:
module breath_state(RST_LED0, RST_LED1, RST_LED2, RST_LED3,
S_END0, S_END1, S_END2, S_END3,
CLK,RST); input S_END0;
input S_END1;
input S_END2;
input S_END3; output reg RST_LED0 = 1'b0;
output reg RST_LED1 = 1'b0;
output reg RST_LED2 = 1'b0;
output reg RST_LED3 = 1'b0; input CLK;
input RST; parameter S0 = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3,
S4 = 3'd4,
S5 = 3'd5,
S6 = 3'd6,
S7 = 3'd7; reg [2:0] state = 3'd0; always @(posedge CLK)
begin
if(!RST)
begin
state = S0; RST_LED0 = 1'b0; //熄灭所有灯
RST_LED1 = 1'b0;
RST_LED2 = 1'b0;
RST_LED3 = 1'b0;
end
else
begin
case(state)
S0: begin
if(S_END0) begin state <= S1; end
else begin
RST_LED0 <= 1'b1; // 仅LED0表演
RST_LED1 <= 1'b0;
RST_LED2 <= 1'b0;
RST_LED3 <= 1'b0;
end
end
S1: begin
if(S_END1) begin state <= S2; end
else begin
RST_LED0 <= 1'b0;
RST_LED1 <= 1'b1; // 仅LED1表演
RST_LED2 <= 1'b0;
RST_LED3 <= 1'b0;
end
end
S2: begin
if(S_END2) begin state <= S3; end
else begin
RST_LED0 <= 1'b0;
RST_LED1 <= 1'b0;
RST_LED2 <= 1'b1; // 仅LED2表演
RST_LED3 <= 1'b0;
end
end
S3: begin
if(S_END3) begin state <= S4; end
else begin
RST_LED0 <= 1'b0;
RST_LED1 <= 1'b0;
RST_LED2 <= 1'b0;
RST_LED3 <= 1'b1; // 仅LED3表演
end
end
S4: begin
if(S_END2) begin state <= S5; end
else begin
RST_LED0 <= 1'b0;
RST_LED1 <= 1'b0;
RST_LED2 <= 1'b1; // 仅LED2表演
RST_LED3 <= 1'b0;
end
end
S5: begin
if(S_END1) begin state <= S0; end
else begin
RST_LED0 <= 1'b0;
RST_LED1 <= 1'b1; // 仅LED1表演
RST_LED2 <= 1'b0;
RST_LED3 <= 1'b0;
end
end
S6: begin
state <= S0; // 多余状态,无条件返回
end
S7: begin
state <= S0; // 多余状态,无条件返回
end
endcase
end end endmodule
2.3 逻辑验证
整理好各个模块以后,编译一下,看看生成出来的逻辑。
FIG2.3综合后的RTL视图网表
顶层只做连接各个模块,那么在RTL视图中就是几个绿色的小方块儿表示了;排列的还是非常整齐的,对照连线,确定一下所有的线连接是正确的。再就是检查一下状态转换图。
FIG2.4 综合后的状态机视图
对照视图下边的状态转换表,选中某根连线就可以在表格中直接高亮显示转换的初始状态,转换条件,下一状态等丰富信息。因为生成的状态机和预期的是一样的,所以就不再验证它的正确性了;配置好芯片引脚,将编程文件下载到实际电路板中,看看效果。
因为博客中不能插入视频,所以将拍好的视频上传到专门的视频网站,生成一个链接,点击进去就可以观看了,也非常方便。
实际效果:http://v.youku.com/v_show/id_XODMxOTY0MzQ0.html
3.Conclusion
对于时序逻辑,采用状态机的方法至关重要!逻辑的设计需要非常清晰,对于状态机的设计,可以先画出状态转换图,然后再进行编写文件;对于逻辑还不清晰的地方,需要认真在草稿纸上画画。
关于编码的规范;对逻辑设计我也是刚刚起步,才学不到一年,更加关注的是逻辑综合后电路的正确性,所以没有对编码进行统一的规范;这方面我也会多多去学习,尽量将文件写的好一点,通用一点。
写一点感受。逻辑设计和编写程序确实有很大的差别,也是各有所长吧;逻辑电路从大的范围来讲,分为组合逻辑和时序逻辑,有各自实现的方式,对于一个要求实现的逻辑,首先要做的就是把它完全分析清楚,将它们的波形都给画出来,然后再考虑哪部分使用组合逻辑,哪部分使用时序逻辑,最后就是将这些小块块连接起来做整合,设计采用的是自顶向下,而实现的方法可以是自下而上。相对逻辑设计,编程就显得不那么精准了,但是灵活性很高,特别适合做复杂的事情,而且总体看来它就是一个时序的,写好的指令是一步步往下走的,对硬件的理解要求不会太高,从而将注意力转移到如何实现上来。我觉得没有必要将它们严格的区分开来,也没有必要将它们混为一谈来对待,它们各自有优缺点,使用的时候只是转变一下逻辑而已。
4.Reference
[1] Verilog 数字系统设计教程(第二版) 夏宇闻
[2] Verilog HDL 高级数字设计(第二版) Michael D.Ciletti
5. Platform
1).Quartus II Version 9.1 Build 222
2).Microsoft Office Visio Professional 2003 SP3
6.Attachment
工程附录文件:http://i.cnblogs.com/Files.aspx
(原创)基于FPGA的调光流水灯(Verilog,CPLD/FPGA)的更多相关文章
- (原创)基于MCU的频率可调,占空比可调的PWM实现(MCU,MCS-51/MSP430)
1.Abstract 做这个是受朋友之邀,用在控制电机转动的方面.他刚好在一家好的单位实习,手头工作比较多,无暇分身,所以找我帮忙做个模型.要求很明晰,PWM的频率在0~1KHz范围内,占空比 ...
- 基于MATLAB2016b图形化设计自动生成Verilog语言的积分模块及其应用
在电力电子变流器设备中,常常需要计算发电量,由于电力电子变流器设备一般是高频变流设备,所以发电量的计算几乎时实时功率的积分,此时就会用到一个积分模块.发电量计算的公式如下:Q=∫P. FPGA由于其并 ...
- cpld fpga 区别
cpld fpga 区别 系统的比较,与大家共享: 尽管FPGA和CPLD都是可编程ASIC器件,有很多共同特点,但由于CPLD和FPGA结构上的差异,具有各自的特点: ①CPLD更适合完成各种算法和 ...
- 《FPGA全程进阶---实战演练》第一章之FPGA介绍
1 什么是FPGA FPGA也即是Field Programmable Gate Array的缩写,翻译成中文就是现场可编程门阵列.FPGA是在PAL.GAL.CPLD等可编程器件的基础上发展起来的新 ...
- FPGA的EPCS 配置的2种方法 FPGA下载程序的方法(EPCS)
使用主动串行配置模式对Cyclone FPGA进行配置前,必须将配置文件写入串行配置器件EPCS.将配置文件写入EPCS的方法有三种: (1)在Quartus II的Programmer中,通过专门与 ...
- FPGA中改善时序性能的方法_advanced FPGA design
本文内容摘自<advanced FPGA design>对应中文版是 <高级FPGA设计,结构,实现,和优化>第一章中的内容 FPGA中改善时序,我相信也是大家最关心的话题之一 ...
- CPLD/FPGA厂商概述 .
随着可编程逻辑器件应用的日益广泛,许多IC制造厂家涉足PLD/FPGA领域.目前世界上有十几家生产CPLD/FPGA的公司,最大的三家是:ALTERA,XILINX,Lattice,其中ALTERA和 ...
- (原创)用Verilog实现一个参数化的呼吸灯(Verilog,CPLD/FPGA)
1.Abstract 观察到一个有趣的现象,每当把Apple笔记本合上的时候,那个白色的呼吸灯就会反复地由暗渐明,然后又由明渐暗,乍一看就像Apple笔记本在打盹休息一样,十分可爱!于是突发奇 ...
- (原创)defparam的应用(Verilog,CPLD/FPGA)
1.Abstract 在同一个模块被多次例化的时候,改变参数构建不同的硬件实体是一个很好的选择.特别是今天帮一个朋友调试一个比较复杂的逻辑,深有体会.这个也是一个小技巧,回来也查了许多资料,强 ...
随机推荐
- 关于提交form不刷新的问题
最近在做一个项目,除去主页面是html页面,点击菜单按钮都由ajax加载生成,在这种情景下,F5刷新或者提交form表单就会将页面回复到刚刚打开主页面. 现在有一个这样的场景,点击子菜单生成一个子页面 ...
- 【转】用C#调用Windows API向指定窗口发送
一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...
- strlen和sizeof
1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型.该类型保证能容纳实现所建立的最大对象的字节大小. 2.sizeof是算符,strlen是函数. ...
- oracle net manager的配置文件tnsnames.ora位置
配置文件所在的路径:C:\app\Ling-PC\product\11.2.0\client_1\network\admin (红色为安装的盘符位置)
- TIJ读书笔记08-数组的初始化和可变长参数形参
TIJ读书笔记08-数组的初始化和可变参数形参 数组 数组的声明 数组的初始化和赋值 可变参数列表 数组 相同类型的,用一个标识符名称封装到一起的一个对象序列或者基本数据类型序列叫数组.(多么严谨的概 ...
- 编程范式 epesode7,8 stack存放指针类型and heap,register
这一节从后往前写. ____stack and heap ___stack由 汇编语言操控管理,数据先入后出. 栈是存放局部变量,函数调用子函数时,该函数在栈中占用的空间会增大,用于存放子函数的局部变 ...
- 终极优化_详解Win7旗舰版系统中可以关闭的服务
Win7旗舰版系统是一款功能强大的系统,不过对于很多用户很多功能却使用不上,而支持功能的很多服务也多少占用了系统资源,那么我们可以通过关闭一些不使用的服务来达到让win7系统运行速度加快的目的.下面小 ...
- C# 中的IOCP线程池
原文地址:http://www.theukwebdesigncompany.com/articles/iocp-thread-pooling.php PartOne : Introduction 当使 ...
- Spring MVC 文件上传
1.form的enctype=”multipart/form-data” 这个是上传文件必须的 2.applicationContext.xml中 <bean id=”multipartReso ...
- 浅析Java内存模型
概述 Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量是线程共享的,存在竞争问题的. Java内存模型规定了所有的变量 ...