集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 2394|回复: 6

FPGA经典设计案例

[复制链接]
zxopenfq 发表于 2021-4-21 14:41:54 | 显示全部楼层 |阅读模式
案例1. 当收到en=1后,dout产生一个宽度为10个时钟周期的高电平脉冲。
需要说明,根据看波形规则,在第3个时钟上沿的时候,看到en==1,根据功能要求,上升沿之后dout就会变为1。10个时钟周期后,dout将变为0。
从功能要求中,看到数字10,我们就知道要计数,并且是dout==1的次数为10个。所以我们计算的是dout==1的时钟次数,并且是10次。为此,补充一个计数器信号cnt,更新后的波形如下图。
计数器cnt要遵守如下原则。
初值一定为0。
除了最后一个,在时钟上升沿,看到dout==1,就将cnt值加1
在时钟上升沿时看到dout==1,并且是最后一个时,cnt值不加1,直接清零。
从功能要求和波形图,我们确认,计数器cnt是对dout==1进行计数,并且一共数10个。为此,在GVIM编辑器中输入“Jsq”并回车,将出现如下代码。
在第13行,输入dout==1,在第14行代码中,输入10-1,这样就完成了计数器设计。
代码解释:第1至第11行,是一个时序always的代码。该代码要描述的功能是:
在时钟clk上升沿或者复位rst_n的下降沿的时候,always就对cnt判断条件并变化一次。具体变化过程如下:
如果是rst_n==0,则将cnt变为0。
否则(即rst_n==1),如果add_cnt有效,也就是为1的时候。继续判断条件并执行。
如果end_cnt有效,即end_cnt==1,则将cnt变为0。
否则(即end_cnt==0),cnt就自加1。
否则(即rst_n==1且add_cnt==0的时钟),cnt保持不变。
上面代码中add_cnt表示计数器加1条件,end_cnt表示计数器数到最后一个。
上面代码描述过于复杂,其实概括起来,功能就是:时钟上升沿时,如果计数器加1条件有效,并且是数到最后一个,则计数器清零;如果计数器加1条件有效,但不是最后一个,则计数器就加1;其他时候,计数器就保持不变。
那么加1条件,即add_cnt是什么呢?在第13行进行了定义。该行代码表示,dout==1就是计数器的加1条件。
那么结束条件,即end_cnt是什么呢?在第14行进行了定义。该行代码表示,数到10个就结束。其中我们关注的是那个数字10,而-1是固定的格式。
add_cnt && cnt==10-1,含义是表示“数到第10个的时候”,add_cnt &&cnt==x-1表示“数到第x个的时候”。记住这个规则。end_cnt==1也表示数完了。
设计好计数器cnt后,我们就可以设计输出信号dout了。仔细分析dout,该信号有两个变化点:变1和变0。我们分析原因,dout变1是由于收到en==1;dout变0,则是数到了10个或者是数完了。所以综上所述,dout的代码是:
至此,我们完成了主体程序的设计,接下来补充module的其他部分。
将module的名称定义为my_ex1。并且我们已经知道该模块有4个信号:clk、rst_n、en和dout。为此,代码如下:
其中clk、rst_n和en是输入信号,dout是输出信号,并且4个信号都是1比特的,根据这些信息,我们补充输入输出端口定义。代码如下:
接下来定义信号类型。
cnt是用always产生的信号,因此类型为reg。cnt计数的最大值为9,需要用4根线表示,即位宽是4位。add_cnt和end_cnt都是用assign方式设计的,因此类型为wire。并且其值是0或者1,1个线表示即可。因此代码如下:
dout是用always方式设计的,因此类型为reg。并且其值是0或者1,1根线表示即可。因此代码如下:
至此,整个代码的设计工作已经完成。整体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module my_ex1(
     clk      ,
     rst_n    ,
     en       ,
     dout      
);
input    clk     ;
input    rst_n   ;
input    en      ;
output   dout    ;

reg [ 3:0]  cnt     ;
wire        add_cnt ;
wire        end_cnt ;
reg         dout    ;


always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign add_cnt = (dout==1);      
assign end_cnt = add_cnt && cnt==10 -1 ;  

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout <= 0;
    end
    else if(en==1)begin
        dout <= 1;
    end
    else if(add_cnt && cnt==10-1)begin
        dout <= 0;
    end
end

endmodule
  如果你觉得有用的话,就请你回个贴或者赞,证明我的付出没有白费,大家都不容易,q328908175,让我们共同学习。
lihongkun16 发表于 2021-4-22 08:43:18 | 显示全部楼层
FPGA经典设计案例
zhangyukun 发表于 2021-4-22 10:04:16 | 显示全部楼层
FPGA经典设计案例
大鹏 发表于 2021-4-23 08:22:13 | 显示全部楼层
FPGA经典设计案例
zxopenluyutong 发表于 2021-4-23 09:30:18 | 显示全部楼层
FPGA经典设计案例
zxopenhl 发表于 2022-2-21 09:29:40 | 显示全部楼层
FPGA经典设计案例
大鹏 发表于 2022-3-17 15:17:53 | 显示全部楼层
FPGA经典设计案例
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

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

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

GMT+8, 2024-11-1 11:47 , Processed in 0.061283 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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