集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 16654|回复: 29

FPGA初级课程第五讲 呼吸灯

[复制链接]
lcytms 发表于 2016-11-3 19:35:46 | 显示全部楼层 |阅读模式
本帖最后由 lcytms 于 2016-11-3 20:40 编辑

FPGA初级课程
第五讲 呼吸灯

Hi,大家好!我是至芯科技的李老师。
今天讲课的题目是:呼吸灯。
本节课我先简要地介绍一下呼吸灯的物理原理,然后实际演示一下呼吸灯驱动逻辑电路的建模与仿真,最后下板查看效果。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:09:58 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-3 21:08 编辑

什么是呼吸灯呢?

没有听说过的同学,可能觉得比较新鲜。
顾名思义,就是像人的呼吸一样,逐渐变强,然后逐渐变弱,依次循环。
耳听为虚,眼见为实。
看看我做好的至芯ZX_1开发板上的led呼吸灯吧。
这有两个灯亮着,一个灯是逐渐变亮,5s之后突然熄灭,依次循环,这是靠开发板右侧的led。这显然不是渐强渐弱的呼吸灯。
而靠开发板左侧另一个灯则是逐渐变亮,5s之后逐渐变弱,10s一个循环。
没错,这就是我们要讲的呼吸灯。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:13:24 | 显示全部楼层
看到这两个灯,我们是不是会联想起这样两个波形,锯齿波和三角波呢?

请看guagle软件上面的波形。请看锯齿波和三角波。

是不是强弱变化的节奏很类似呢?
没错,正是如此。
大家有没有发现,三角波的右半边波形实质上就是左半边的镜像呢?

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:15:26 | 显示全部楼层
实质上,如果我们得到了更基础的锯齿波,我们如果将偶数周期的波形取补值,就可以得到三角波。

那我们就先讨论锯齿波吧。
锯齿波又如何用FPGA实现呢?
当然也可以用DA器件。但是更普遍的是使用PWM技术。
也就是用不同占空比的波形来表达驱动的强弱。
还是结合实例,好理解一点。来看做好的仿真波形。
为了方便观察,我们输出了对应的脉冲波形。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:15:59 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-3 20:52 编辑

占空比变化从0一直变化到100%。
比如说是分成100份,我们通常是从1到100循环变化。
仿真波形中为了方便观察,分辨率只有5,也就是说从1到5地变化。
我们的演示做得分辨率更高,是分成了1000份,也就是说从1到1000进行变化。
第1个周期占空比为1‰,第2个周期占空比为2‰,第3个周期占空比为3‰,依次递进,第1000个周期占空比为1000‰,然后回到第一个周期,如此循环。
当然了,实现1‰的占空比,至少要1000个脉冲,对不对?
第1个脉冲为高电平,其余999个脉冲为低电平,这就是1‰的占空比。
因此,要实现以上需求,需要1000*1000个脉冲来完成一个逐渐变强的爬坡波形。
比如说这个波形持续5s,那么每个脉冲的周期就是5us,相当250个时钟,因为50MHz时钟对应时钟周期为20ns。

因此,我们要生成一个间隔为5us的基础脉冲。
在此基础上,依次生成间隔为1000倍和1000*1000倍的脉冲,对应为间隔5ms的脉冲和间隔5s的脉冲。
 楼主| lcytms 发表于 2016-11-3 20:17:24 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-3 21:02 编辑

好了锯齿波的物理原理既然清楚了,就来建模仿真吧。
建立新工程文件夹pulse。
编写pulse.v文件。
module pulse(clk, rst_n, led);

        input clk, rst_n;

        output [3:0] led;
       
        reg [31:0] count5us, count5ms, count5s;   //, count_duty
        reg flag5us, flag5us_r, flag5ms, flag5s;
        reg dutysawtooth;
        reg switch5s;
       
        parameter T5us = 250;                         // 5us/20ns = 250
        parameter CNT1k = 1000;                 // 1000
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        count5us <= 0;
                                        flag5us <= 0;
                                end
                        else
                                begin
                                        if (count5us < T5us - 1)
                                                begin
                                                        count5us <= count5us + 1;
                                                        flag5us <= 0;
                                                end
                                        else
                                                begin
                                                        count5us <= 0;
                                                        flag5us <= 1;
                                                end
                                end
                end

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                flag5us_r <= 0;
                        else
                                flag5us_r <= flag5us;
                end
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        count5ms <= 0;
                                        flag5ms <= 0;
                                end
                        else
                                begin
                                        if (!flag5us)
                                                flag5ms <= 0;
                                        else
                                                begin
                                                        if (count5ms < CNT1k - 1)
                                                                begin
                                                                        count5ms <= count5ms + 1;
                                                                        flag5ms <= 0;
                                                                end
                                                        else
                                                                begin
                                                                        count5ms <= 0;
                                                                        flag5ms <= 1;
                                                                end
                                                end
                                end
                end

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        count5s <= 0;
                                        flag5s <= 0;
                                end
                        else
                                begin
                                        if (!flag5ms)
                                                flag5s <= 0;
                                        else
                                                begin
                                                        if (count5s < CNT1k - 1)
                                                                begin
                                                                        count5s <= count5s + 1;
                                                                        flag5s <= 0;
                                                                end
                                                        else
                                                                begin
                                                                        count5s <= 0;
                                                                        flag5s <= 1;
                                                                end
                                                end
                                end
                end

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                dutysawtooth <= 0;
                        else if (flag5us)
                                begin
                                        if (count5ms <= count5s)                        //需要重点理解的地方,对应第n个周期占空比为n‰
                                                dutysawtooth <= 1;
                                        else
                                                dutysawtooth <= 0;
                                end
                end

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                switch5s <= 0;
                        else
                                begin
                                        if (flag5s)
                                                switch5s <= ~switch5s;
                                        else
                                                switch5s <= switch5s;
                                end
                end
       

        wire dutysawtooth_o;
        assign dutysawtooth_o = dutysawtooth & flag5us_r;
       

////////////////////////////////////////////////////////////
        wire dutytriangle;

        assign dutytriangle = switch5s ? ~dutysawtooth : dutysawtooth;
       
        wire dutytriangle_o;
        assign dutytriangle_o = dutytriangle & flag5us_r;
////////////////////////////////////////////////////////////

//        assign led = {3'b111, ~dutysawtooth_o};
        assign led = {~dutytriangle, 2'b11, ~dutysawtooth};
//        assign led = {4{~dutytriangle}};
//        assign led = {4{~dutysawtooth}};
       
endmodule

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:26:10 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-3 21:02 编辑

对编好的pulse.v模块进行分析综合检查。

再编写Testbench。新建pulse_tb.v文件。
`timescale 1ns/1ps

module pulse_tb;

        reg clk, rst_n;

        wire [3:0] led;

        pulse #(.T5us(5), .CNT1k(5)) dut(.clk(clk), .rst_n(rst_n), .led(led));
       
        initial begin
                clk = 1;
                rst_n = 0;
                #200.1
                rst_n = 1;

                #10_000                $stop;
        end

        always #10 clk = ~clk;

endmodule

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:31:55 | 显示全部楼层
设置仿真,查看锯齿波的led灯输出的仿真结果。

在锯齿波的基础上,改写pulse.v文件,增加三角波的led灯输出。

设置仿真,查看锯齿波 + 三角波的led灯输出的仿真结果。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:32:55 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-3 20:36 编辑

参照.tcl文件设置好FPGA管脚

参照EP4CE10F17C8Nzx_1.tcl文件内容,对FPGA芯片管脚进行设置。

EP4CE10F17C8Nzx_1.tcl文件相关内容如下所示。FPGA芯片配置结果如图所示。

        #set_global_assignment -name FAMILY "Cyclone IV"
        #set_global_assignment -name DEVICE ep4ce10f17c8n

set_location_assignment PIN_E1    -to    clk         
# LED
set_location_assignment PIN_T12   -to   LED[0]         
set_location_assignment PIN_P8    -to   LED[1]         
set_location_assignment PIN_M8    -to   LED[2]         
set_location_assignment PIN_M10   -to   LED[3]         
       
# KEY 轻触按键
set_location_assignment PIN_L3    -to   key[0]         

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-11-3 20:35:46 | 显示全部楼层
.sof文件下载到FPGA
全编译FPGA工程,生成.sof文件,连接至芯ZX-1开发板并上电。
打开Programmer通过Jtag口,将.sof文件下载到FPGA进行在线仿真。
.sof文件下载界面如下图所示。

本帖子中包含更多资源

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

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

本版积分规则

关闭

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

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-12-23 23:57 , Processed in 0.067951 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表