当前位置:   article > 正文

FPGA基于Vivado开发,设计顶层文件Top.v_vivado顶层文件

vivado顶层文件

一通废话

首先得承认,我并不是主动拥抱顶层文件这套思路的,原因很简单,能用就行干嘛费劲搞那么多东西。起初知识点亮一个LED灯,整一个半加器的简单模拟,也确实根本用不上。后边工程有一定的负责度,例如设计数字时钟,LCD1602驱动设计等等,这个时候我就发现了层次化设计的一个便捷之处,在于他们方便复用,只需要定义好一个功能Module,可以在仿真 – 下板之间无缝衔接,增加了自己开发的效率,减少不必要的注释,感兴趣可以接着往下看。

另外自己上述两个工程博客连接:

为什么需要层次化设计

一图胜千言,引用野火开发板他们家的资料(文末备注)里说明复用的思想在哪个地方。举个例子,比如我现在定义了一个橙色的模块,我现在第一层(绿色)的需求是设计一个数字时钟,那么第二层拆分开就是定时1秒(蓝色),定时1分钟(橙色)、定时1小时(红色)。接着蓝色的定时1秒,我再通过其他小模块继续拆分。那么大家有没有想过一个问题,都是同样的计数/计时,秒钟/分钟/时钟不都是一样的吗,只不过一个是定时1秒,一个是60秒,一个是3600秒。是的,我们完全可以统一写一个定时模块(比如第三层蓝色功能模块1_1),改变定时的值(1/6/3600)即可。

也就是说,层次化的设计思想,其实就是拆分需求,减少重复代码统一集成一个公用的模块,这就达到了Module复用的功能。说起来非常高端,我们通过一个简单例子来说明下如何使用吧,时间才是检验真理的唯一标准。
在这里插入图片描述

怎么使用

首先要申明一点,目前入门FPGA的阶段属于非常非常,所有工程代码、工程逻辑都可能存在错误,希望各位同学老师能够指出,同时也参考了大量的互联网上优质内容,在这里一并感谢,基于这个原因也决定将核心逻辑进行共享。请勿做一切商业用途。接下来会以我在数字时钟那篇的博客,讲一讲大概的逻辑,具体实操大家可以移步数字时钟的那篇博客。

这里是引用

带大家看三个文件,第一个是功能模块长什么样;第二个是理解顶层文件Top.v长什么样,到底是怎么复用的;第三个是了解testbench文件是如何设计的,和顶层文件有什么区别。

clock1.v文件:

//数字时钟模块
module clock1(
    sec,
    min,
    hour,
    rst,
    sys_clk_p,
    sys_clk_n,
    clk_out1,
    led_out1,
    led_out2
    );
       
input      rst;
input      sys_clk_p;            // Differential input clock 200Mhz
input      sys_clk_n;            // Differential input clock 200Mhz
output     clk_out1;  
output [7:0]  sec,min;
output [7:0]  hour;
output    led_out1;
output    led_out2;
reg    [7:0]  sec=0;
reg    [7:0]  min=0;
reg    [7:0]  hour=0;
reg    [32:0] cnt;
reg    clk_div;
reg    led_out1;
reg    led_out2;


//分频部分  50MHz - 1Hz
always @ ( posedge clk_out1 or posedge rst)begin
	篇幅原因略去代码
end

// 秒钟部分
always @ ( posedge clk_div  or posedge rst)begin
	篇幅原因略去代码
end

//分钟部分
always @ ( posedge clk_div or posedge rst)begin
	篇幅原因略去代码
end

// 时钟部分
always @ ( posedge clk_div or posedge rst)
	篇幅原因略去代码
end

endmodule
  • 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
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

这个模块该有的功能全都有,篇幅原因省去的代码其实都基本一个样。需要关注到的是这个module里边详细定义了secminhour这三个变量,并且都是output类型。因为我们是对顶层设计的举例子,代码详细功能不在这里讲解。接下来一并看剩下两个文件。

Top.v文件

module TOP(
    input rst,
    input sys_clk_p,
    input sys_clk_n,
    output clk_out1,
    output led_out1,
    output led_out2
    );
//***********差分时钟50MHz *****************************************
wire   sys_clk_p;
wire   sys_clk_n;
wire   rst;
wire   clk_out1; 
//***********数字时钟****************************************
wire   led_out1;
wire   led_out2;

//时钟模块初始化
clock1 clock(
    .led_out1(led_out1),
    .led_out2(led_out2),
    .rst(rst),
    .sys_clk_p(sys_clk_p        ),
    .sys_clk_n(sys_clk_n        ),
    .clk_out1(clk_out1        )
    );

//PLL分频的代码

endmodule
  • 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
  • 29
  • 30

Testbench文件

`timescale 1ns / 1ns

module clock1_tb();

//***********??????*****************************************
reg   sys_clk_p;
wire  sys_clk_n;
reg     rst;
wire    clk_out1; 
//***********??????*****************************************
wire [7:0]   sec;
wire [7:0]   min;
wire [7:0]   hour;
wire   led_out1;
wire   led_out2;

//初始化系统时钟
initial begin
    sys_clk_p = 1'b0;
	略去代码
end

//数字时钟初始化
clock1 clock(
    .led_out1(led_out1),
    .led_out2(led_out2),
    .sec(sec),
    .min(min),
    .hour(hour),
    .rst(rst),
    .sys_clk_p(sys_clk_p        ),
    .sys_clk_n(sys_clk_n        ),
    .clk_out1(clk_out1        )
    );    
    
//PLL时钟分频

endmodule
  • 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
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

可以看两个文件夹,代码基本都是一模一样的,定义好端口(input/output/wire/reg等),初始化clock模块如何结束。

  • 区别1:Top.v顶层文件没有申明sec/min/hour这几个端口,但testbench文件申明了;
  • 区别2:testbench文件需要初始化相关的值、时钟等,但Top.v文件不需要;

这里重点关注第一点,我们这里并不需要把secminhour这三个寄存器变量输出(需要制定引脚),所以我们在Top.v文件里边不声明他的输入输出类型,但实际下板却并不影响clock功能的实现,因为模块的功能实现与否,和你是否声明并无关系。你申明了,他就展示出来,不声明他就不展示出来,但功能一直都在实现。

这样写的一个好处就是,我们只需要写好一个module文件,在仿真测试,以及下板验证的时候都能够很快、很简单地实现,而不用大量复制代码,在两头切换。

补充

在testbench文件我们对他进行声明了,当然了,因为我们仿真的时候需要这个变量来看看,初步确认他的功能是好的,实际下板我们并不需要把秒、分、时都输出出来(设想一个寄存器变量占8位,3个就是24位,并没有这么多引脚给你占用)。当然如果你有意为之,你也可以如下设置这三个变量,那么你便需要设置相关引脚并进行下一步。

此时的Top.v文件

module TOP(
    output sec,
    output min,
    output hour,
	…………
	同上
    );

wire [7:0]   sec;
wire [7:0]   min;
wire [7:0]   hour;

//***********差分时钟50MHz *****************************************
同上

//***********数字时钟****************************************
同上

//时钟模块初始化
同上

//PLL分频的代码
同上

endmodule
  • 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

不声明,但功能实现时候,引脚的截图:

在这里插入图片描述

不声明,功能也实现时候,引脚的截图:
在这里插入图片描述

总结

  • 本文稍微介绍了下什么是层次化设计,举了个数字时钟的例子
  • 以数字时钟为例,讲了如何在顶层文件Top.v复用定义好的module(Testbench也可以理解为一种顶层文件);
  • 顶层文件选择性地不声明相关引脚,减少引脚使用;仿真申明引脚以便查看功能完整性和正确性;

参考

以上。

如果你觉得这篇文章对你有帮助,请为我点个赞谢谢

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/148001
推荐阅读
相关标签