目录
1.移位实现LED流水灯
1.1创建工程及源文件代码
1.1.1源代码
利用计数器计数到500ms,让LED的8位每次左移一位。当复位后/移动至最左边时,让LED灯归位。犯的错误:1.counter<=counter+1'd1,写成了等号,导致仿真波形偶数的led灯无高电平,就是一个瞬间的脉冲,还有其他几处。
module run_led(
clk,
reset,
led
);
input clk;
input reset;
output reg [7:0]led;
reg [24:0]counter;
always@(posedge clk or negedge reset)
if(!reset)
counter<=0;
else if(counter == 25_000_000-1)
counter<=0;
else
counter<=counter+1'd1;
always@(posedge clk or negedge reset)
if(!reset)
led<=8'b0000_0001;
else if(counter == 25_000_000-1)
begin
if(led==8'b1000_0000 | led==8'b0000_0000)
led<=8'b0000_0001;
else
led<=led<<1;
end
else
led<=led;
endmodule
1.1.2仿真代码
时钟也是每10ns翻转一次,复位信号刚开始为低电平,延时201ns后变高,再延时4s,包装8个led灯的翻转。
`timescale 1ns / 1ns
module run_led_tb();
reg clk;
reg reset;
wire [7:0]led;
run_led run_led(
.clk(clk),
.reset(reset),
.led(led)
);
initial clk=0;
always #10 clk=~clk;
initial begin
reset=0;
#201;
reset=1;
#2000_000_000;
#2000_000_000;
$stop;
end;
endmodule
1.1.3仿真
与预期一致,然后选择好引脚,烧录程序到开发板。
1.2实验结果
8个LED灯循环闪烁,与仿真波形一致。
1.2.1总结
修改源代码后,保存后还要重新生成bit文件才行,不然烧录的还是之前的程序。
2.循环移位实现LED流水灯
即将LED的前6位与第7位拼接起来,即可每次循环转一次。实验现象与之前一致。
begin
led<={led[6:0],led[7]};
end
3.38译码器实现LED流水灯
3.1原理
将之前写的38译码器模块直接调用,使用一个计数器循环计数0~7,将对应的值直接对应到输出。
3.2源程序
添加新的源文件,将1部分的代码复制,调用之前的38模块,添加现有源文件,需要勾选第二个copy框,意思是复制38译码器到这个工程来,否则就是在原来的工程上进行修改。
1.3位的计数器计满后不用管,自动溢出清0。
2.关于LED的驱动问题,led是由下一层38译码器驱动,run_led2作为上层,led只是起到一根导线的作用,从下层穿透到上层,最终作为端口引出。任何一个模块,在被例化的时候,连接到其输出端口的信号,都应该是wire型。
module run_led2(
clk,
reset,
led
);
input clk;
input reset;
output wire [7:0]led;
reg [24:0]counter;
always@(posedge clk or negedge reset)
if(!reset)
counter<=0;
else if(counter == 25_000_000-1)
counter<=0;
else
counter<=counter+1'd1;
reg [2:0]counter2;
always@(posedge clk or negedge reset)
if(!reset)
counter2<=0;
else if(counter == 25_000_000-1)
counter2<=counter2+1'd1;
decoder_3_8 decoder_3_8(
.A2(counter2[2]),
.A1(counter2[1]),
.A0(counter2[0]),
.Y0(led[0]),
.Y1(led[1]),
.Y2(led[2]),
.Y3(led[3]),
.Y4(led[4]),
.Y5(led[5]),
.Y6(led[6]),
.Y7(led[7])
);
endmodule
实验现象与之前一样。