上个例子为用FPGA控制使一个led以1ms速度翻转,如果想改变led翻转速度,最直观的想法是重新计算计数器的值,然后进行更改。问题是如果需要频繁的更改,或增加很多不同的led,就需要填加很多修改计算好的模块,这样就不是很方便,所以还有其他的解决办法。
方法一、一个模块在顶层多次调用,在顶层改变变化的参数
底层:
module led01(
Clk,
Rst_N,
Cnt_max,
Led
);
input Clk;
input Rst_N;
input [15:0]Cnt_max;
output reg Led;
//LED低电平点亮,使一个led以1ms速度翻转。
reg [15:0]cnt;
//写一个计数器
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
cnt <= 0;
else if(cnt == Cnt_max) // 1ms = 1_000_000/20 -1 = 49_999
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
Led <= 1;
else if(cnt == Cnt_max)
Led <= ~Led; //信号在always里赋值,要在前面定义reg型
endmodule
顶层:
led01 led01_u1(
.Clk(Clk),
.Rst_N(Rst_N),
.Cnt_max(49_999),
.Led(Led1)
);
led01 led01_u2(
.Clk(Clk),
.Rst_N(Rst_N),
.Cnt_max(24_999),
.Led(Led2)
);
方法二、使用parameter
底层:
module led02(
Clk,
Rst_N,
Led
);
input Clk;
input Rst_N;
output reg Led;
parameter Cnt_max = 49_999;
//LED低电平点亮,使一个led以1ms速度翻转。
reg [15:0]cnt;
//写一个计数器
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
cnt <= 0;
else if(cnt == Cnt_max) // 1ms = 1_000_000/20 -1 = 49_999
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
Led <= 1;
else if(cnt == Cnt_max)
Led <= ~Led; //信号在always里赋值,要在前面定义reg型
endmodule
顶层:
led02 #(.Cnt_max(24_999)) led02_u3(
.Clk(Clk),
.Rst_N(Rst_N),
.Led(Led3)
);
方法三、使用parameter和defparam
底层:
module led02(
Clk,
Rst_N,
Led
);
input Clk;
input Rst_N;
output reg Led;
parameter Cnt_max = 49_999;
//LED低电平点亮,使一个led以1ms速度翻转。
reg [15:0]cnt;
//写一个计数器
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
cnt <= 0;
else if(cnt == Cnt_max) // 1ms = 1_000_000/20 -1 = 49_999
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_N)
if(!Rst_N)
Led <= 1;
else if(cnt == Cnt_max)
Led <= ~Led; //信号在always里赋值,要在前面定义reg型
endmodule
顶层:
led02 led02_u4(
.Clk(Clk),
.Rst_N(Rst_N),
.Led(Led4)
);
defparam led02_u4.Cnt_max = 12_499;
最终仿真结果: