系列文章目录
二、FPGA学习笔记(二)Verilog语法初步学习(语法篇1)
四、FPGA学习笔记(四)通过数码管学习顶层模块和例化的编写
五、FPGA学习笔记(五)Testbench(测试平台)文件编写进行Modelsim仿真
六、FPGA学习笔记(六)Modelsim单独仿真和Quartus联合仿真
七、FPGA学习笔记(七)verilog的深入学习之任务与函数(语法篇3)
模块例化
在一个模块中引用另一个模块,对其端口进行相关连接,叫做模块例化。
作用:
将模块端口与外部信号按照其名字进行连接,端口顺序随意。
如果某些输出端口并不需要在外部连接,例化时 可以悬空不连接,甚至删除。
input 端口在例化时不能删除,否则编译报错,output 端口在例化时可以删除。
我的理解:
我认为顶层文件的编写,相当在编写嵌入式裸机开发中的main.c文件,需要将各个子文件综合在一起,其中需要将一些变量关联在一起,C语言中采用的extern的声明方式,将变量在不同的文件中调用,FPGA就使用顶层文件的例化将他们关联在一起。
数码管上层调用例子
在正点原子FPGA的开发指南中,在数码管一章中,有一个顶层文件的编写,因为把计时模块和数码管显示的模块分开了,为了实现隔一段时间,数码管显示不同的数字。
计时文件的模块:
数码管显示的模块:
顶层文件的编写:
这里在time_count模块例化的过程中就对MAX_NUM重新赋值。这是第一种写法。
参数定义和传递大全
首先要把外部信号进行模块化,之后要进行引脚的连接。其次就像add_flag这种,因为两个模块公用,所以需要关联在一起。
在time_count文件中:
参考: verilog中参数传递与参数定义中#的作用,说明了参数传递的格式。这里#的意思是参数传递,将TIME_SHOW传递给MAX_NUM。主要应用在当一个模块引用另外一个模块时,高层模块可以改变低层模块用parameter定义的参数值
其他两种写法:(多参数重定义)
//定义带延迟参数的模块
module bus_master;/
/默认的参数值
parameter delay1 = 2;
parameter delay2 = 3;
parameter delay3 = 7;
<模块内部的语句>
...
endmodule
//顶层模块;调用两个bus_master模块
module top;
//用新的延迟参数值调用这两个模块
//用顺序列表把新的参数值传入模块
bus_master #(4,5,6)b1();// b1: delay1 = 4, delay2 = 5, delay3 = 6
bus_master #(9,4) b2(); // b2 :.delay1 = 9,delay2 = 4,delay3 = 7(默认)
//用命名参数把新的参数值传入模块
bus_master # (.delay2(4), delay3(7)) b3();// b2: delay2 = 4, delay3 = 7 ,delay1=2(默认)
//建议使用命名的参数传人方式,使用这种方法减少了产生错误的机会,可增添或删除参数而不需要担心其次序
endmodule
还有另外一种方法:
verilog中defparam的用法及#的用法
这里可以写成:#defparam time_count.MAX_NUM=TIME_SHOW;
同样,有可以修改的参数就有不可以修改的:
localparam:本地参数声明,本地参数不能用参数重新定义( defparam)修改,也不能在实例引用时通过传递参数语句,即#(参数1,参数2,…)的方法修改。
回到数码管的模块内程序
这里MAX_NUM定义的时候不能写空,上层文件可以随便修改,程序方便。
模块复用的例子
通过模块例化实现模块 重用,比如实现了一个LED的闪烁,那么如何让八个LED以不同频率闪烁?
可以通过把该模块进行八次例化,链接不同的LED,斌并且更改他们的计数值实现不同频率闪烁
例子: