原创 FPGA之流水灯

2009-11-9 19:54 3543 10 12 分类: FPGA/CPLD
学习FPGA有一段时间了,但不连续,很多知识都是看了忘,忘了看,而且也不动手实践,只知道抱着一本书死看,造成的后果就是自己在原地踏步,这也正应了那句话:FPGA是一门理论联系实践很强的一门学科,两手都要抓,两手都要硬。
废话就不多说了,找了一块开发版,从下面的文章开始,我将记录下我学习的点滴过程,希望大家多拍砖。。。

按照我的理解,学习,就是要从最简单的学起,不断深入,持之以恒,最终有所成就。
工具:Verilog语言;quartus软件;实验平台任选,能用就成
流水灯应该是最简单的电路了,一般单片机的学习以它为起点,学习FPGA,我们也以它为起点。
假设我们期望实现如下的功能:10个LED灯,先从左边亮到右边,再从右边亮到左边,如此往复。
第一种形式的代码如下:
`timescale 1ns/1ns

module LED(rst_n,clk50M,led);
input rst_n; //复位信号
input clk50M; //时钟信号
output[9:0] led; //LED灯的输出信号

reg[9:0] mled;
reg[23:0] cnt; //计数器
reg dir; //LED等闪烁的方向控制,0,左移,1,右移

always@(posedge clk50M,negedge rst_n)
begin
    if(!rst_n)
        cnt<=24'h0;
    else
    begin
        if(cnt==24'hffffff)
            cnt<=24'h0;
        else
            cnt<=cnt+24'h1;
    end
end

always@(posedge cnt[23],negedge rst_n)
begin
    if(!rst_n)
    begin
        mled<=10'h1;
        dir<=1'b0;
    end
    else
    begin
        if(!dir)
        begin
            mled<={mled[8:0],1'b0};
            if(mled==10'h100)
                dir<=1'b1;
        end
        else
        begin
            mled<={1'b0,mled[9:1]};
            if(mled==10'h2)
                dir<=1'b0;
        end
    end
end

assign led=mled;

endmodule
当然,这里包含了一个行波时钟,编译之后会出来一个警告,这个行波时钟一共代个十一个触发器。我个人的观点是,用这样一个行波时钟,应该问题不大。当然这只是我个人的想法,希望有懂的人给予指证。
第二种代码是在第一种代码的基础上进行了修改,采用同步设计
`timescale 1ns/1ns

module LED(rst_n,clk50M,led);
input rst_n; //复位信号
input clk50M; //时钟信号
output[9:0] led; //LED灯的输出信号

reg[9:0] mled;
reg[23:0] cnt; //计数器
reg dir; //LED等闪烁的方向控制,0,左移,1,右移

always@(posedge clk50M,negedge rst_n)
begin
    if(!rst_n)
        cnt<=24'h0;
    else
    begin
        cnt<=cnt+24'h1;
    end
end

always@(posedge clk50M,negedge rst_n)
begin
    if(!rst_n)
    begin
        mled<=10'h1;
        dir<=1'b0;
    end
    else
    begin
        if(cnt==24'hffffff)
        begin
            if(!dir)
            begin
                mled<={mled[8:0],1'b0};
                if(mled==10'h100)
                    dir<=1'b1;
            end
            else
            begin
                mled<={1'b0,mled[9:1]};
                if(mled==10'h2)
                    dir<=1'b0;
            end
        end
    end
end

assign led=mled;

endmodule
但是第二种代码的最高运行频率没有第一种高,资源占用也比第一种多,具体的我现在也没搞明白,希望高手指点。
PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户152969 2009-10-28 10:06

楼上说的对,有空多交流。。。

用户222522 2009-10-25 17:43

我觉得第二种是因为会生成一大堆组合逻辑用于比较计数器cnt有没有计到24'hffffff,这样产生的时延就大了,再加上后级逻辑的时延,就会使频率下降,而且占用的资源(LUT)也多了。解决办法可以是把比较的部分用寄存器打一拍,然后频率会高一点但不多,但使用资源将更多。 其实第一种方法可以啊,因为产生的时钟是经过寄存器输出的,不会存在毛刺
相关推荐阅读
用户152969 2009-10-30 14:13
FPGA流水灯之仿真波形
上一篇日志给出了关于流水灯的代码,这篇文章介绍一下如何对其进行仿真。仿真工具:ModelSim1、双击ModelSim图标,打开ModelSim;2、点击File->New->Projec...
EE直播间
更多
我要评论
2
10
关闭 站长推荐上一条 /3 下一条