一、理解
在初次学习FPGA时,大多数的实例为编写一个计数器,但是当需要同时编写n个不同的计数器时,若继续使用最初始入门时那样一个一个计数器文件的编写,将会非常麻烦,并且耗时耗力,容易出错。因此,若只需要编写一个类似C语言中库函数的函数,然后创建一个新的文件,在新文件中不断的调用该库函数,此时将在一个文件中编写n个不同的计数器。(引入C语言中库函数概念不够准确,此处只为便于理解)。
二、具体过程
1.一个计数器
FPGA编写一个计数器,用来点亮一盏LED灯。
(1)设计代码
//点亮LED灯实验
module led_key(
input clk,
input rst,
input key,
output wire led
);
parameter COUNT_MAX=32'd2999;
reg [31:0]cnt_num=0;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_num<=1'd0;
end
else if (!key) begin
if (cnt_num==COUNT_MAX) begin
cnt_num<=cnt_num;
end
else begin
cnt_num<=cnt_num+1'd1;
end
end
else begin
cnt_num<=32'd0;
end
end
assign led=(cnt_num==COUNT_MAX)?1'd0:1'd1;
endmodule
2.多个计数器
如果需要同时点亮多个流水灯,每次编译文件会非常的麻烦,因此进行模块化设计。
在进行模块例化时,首先需要重新创建一个top顶层文件,用来调用已经写好的模块代码。
module led_key_top(
input wire clk1,
input wire rst1,
input wire [3:0]key_in,
output wire [3:0]led1
);
parameter COUNT_MAX0 = 32'd8000;
parameter COUNT_MAX1 = 32'd12000;
parameter COUNT_MAX2 = 32'd16000;
parameter COUNT_MAX3 = 32'd20000;
led_key #(.COUNT_MAX (COUNT_MAX0))
inst_led_key0(
.clk (clk1),
.rst (rst1),
.key (key_in[0]),
.led (led1[0])
);
led_key #(.COUNT_MAX (COUNT_MAX1))
inst_led_key1(
.clk (clk1),
.rst (rst1),
.key (key_in[1]),
.led (led1[1])
);
led_key #(.COUNT_MAX (COUNT_MAX2))
inst_led_key2(
.clk (clk1),
.rst (rst1),
.key (key_in[2]),
.led (led1[2])
);
led_key #(.COUNT_MAX (COUNT_MAX3))
inst_led_key3(
.clk (clk1),
.rst (rst1),
.key (key_in[3]),
.led (led1[3])
);
顶层文件相当于主函数,而其中的模块相当于子函数,因此在进行多个流水灯设计时,仅仅使用top函数(相当于主函数)即可实现模块化的操作与设计。
注意:下文该语法中 #(.X (Xi))相当于实例化该函数的同时,将新的parameter参数传入,一种固定写法,记住就可!
led_key #(.COUNT_MAX (COUNT_MAX0))
inst_led_key0(
.clk (clk1),
.rst (rst1),
.key (key_in[0]),
.led (led1[0])
);