本次基于FPGA实现流水灯,即让LED[0:7]从左到右依次电量,每个LED灯频闪周期为1s钟,在这里,给出下面三种实现思路:
1、实验思路
1、使用位运算符
在复位时令LED灯为LED=8’b0000_0001,然后每过一秒钟,左移一位,如果LED灯状态为LED=8’b1000_0000,下一次再让LED=8’b0000_0001即可实现流水灯。
2、使用循环位移
使用循环位移和位拼接符,复位时如果我们令led=1000_0000,然后开始计时,我们让led[6:0]和led[7]进行拼接,得到0000_0001,再过一秒,同样进行拼接,得到0000_0010,使用这个方法无需考虑上面的末尾情况。
3、使用3-8译码器
再加入一个计数器,作为状态输入端,我们有8个输出,所以需要三个输入端口,复位令计数器为0,每过一秒状态计数器的值加1,最后状态计数器的值作为3-8译码器的输入端口即可。
2、代码编写
下面给出上面三种思路对应设计文件的verilog代码:
1、使用位运算符
module led_run1(
clk,Reset_n,led
);
input clk;
input Reset_n;
output reg[7:0] led;
reg [24:0] counter;
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
counter<=0;
else if(counter == 24999999)
//else if(counter == 24999) //节约仿真时间
counter <=0;
else
counter <= counter+1;
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
led <= 8'b0000_0001;
else if(counter == 24999999)
//else if(counter == 24999) //节约仿真时间
begin
if(led == 8'b1000_0000) //如果是最后一个灯亮,则再回去
led <= 8'b0000_0001;
else
led <= (led<<1); //如果是其他情况,则左移一位即可
end
endmodule
2、使用循环位移
module led_run2(
clk,Reset_n,led
);
input clk;
input Reset_n;
output reg[7:0] led;
reg [24:0] counter;
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
counter<=0;
else if(counter ==24999999)
//else if(counter == 24999) //节约仿真时间
counter<=0;
else
counter <= counter+1;
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
led<=8'b0000_0001;
else if(counter==24999999)
//else if(counter == 24999) //节约仿真时间
led <= {led[6:0],led[7]}; //使用拼接符,循环左移
endmodule
3、外接3-8译码器
module led_run3(
clk,Reset_n,led
);
input clk;
input Reset_n;
output [7:0] led; //此处led是由底层三八译码器驱动,不需要reg类型,已经在decoder中定义out为reg了
reg [25:0] counter; //为了和前面区分,这里设为1秒的速率
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
counter<=0;
else if(counter == 49999999)
//else if(counter == 24999) //节约仿真时间
counter <=0;
else
counter <= counter+1;
//使用三八译码器,八个输出刚好对应八个LED灯,三个输入利用重新产生一个变量即可
reg [2:0] counter2; //产生三位输出作为三八译码器输出
always@(posedge clk or negedge Reset_n)
if (!Reset_n)
counter2 <= 3'b000;
//else if(counter == 24999)
else if(counter == 49999999)
counter2 <= counter2+1'b1;
//例化3-8译码器模块
decoder_3_8 decoder_3_8(
.a(counter2[2]),
.b(counter2[1]),
.c(counter2[0]),
.out(led)
);
endmodule
编写测试文件,不同的设计文件更改对应的模块名即可
`timescale 1ns/1ps
module led_run_tb();
reg clk;
reg Reset_n;
wire [7:0] led;
led_run3 led_run( //例化led_run1修改对应的前面的标签即可
.clk(clk),
.Reset_n(Reset_n),
.led(led)
);
initial clk=1; //时钟初始值设为1
always #10 clk=!clk; //每延时10ns,时钟翻转一次,这样一个周期就是20ns
initial begin
Reset_n = 0; //复位
#201
Reset_n = 1; // 复位接高电平
#40000000;
$stop;
end
endmodule
3、仿真测试
4、板级验证
生成比特流,烧到开发板即可。
标签:Reset,led,FPGA,clk,LED,流水,input,设计,reg From: https://blog.csdn.net/weixin_50164178/article/details/140676240