verilog基础语法与应用:位操作——流水灯/跑马灯
今天的实验是计数器实验的升级,设计让8个LED灯以每个0.5s的速率循环闪烁
1 移位法实现
1.1 移位方法1
每个LED灯代表一位,共8位,亮为1,灭为0
如何实现这样的逻辑呢?
移位操作即可!
怎么样才能移位呢?
第一个状态需满足最低位为1,然后每次左移1个
- 源代码
module led_run(
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 == 2500_0000-1)
// else if(counter == 2500-1) //为了仿真的时候方便观察,把数字改小
counter <= 0;
else
counter <= counter + 1'd1;
// 用移位方法实现 8个灯循环闪烁
//0000_0001
//0000_0010
//0000_0100
//0000_1000
//0001_0000
//0010_0000
//0100_0000
//1000_0000
always@(posedge clk or negedge reset_n)
if(!reset_n)
led <= 8'b0000_0001;
else if(counter == 2500_0000-1)
// else if(counter == 2500-1) //为了仿真的时候方便观察,把数字改小,现在是0.05ms
begin
if(led==8'b1000_0000)
led <= 8'b0000_0001;
else
led <= led << 1; // '<<' 是左移
end
else
led <= led; // 还未到时间,led灯状态不变 (这句话不写默认也是这样)
endmodule
- 仿真代码
`timescale 1ns / 1ps
module led_run_tb;
reg clk;
reg reset_n;
wire [7:0] led;
led_run UUT(
.clk(clk),
.reset_n(reset_n),
.led(led)
);
initial clk = 1;
always#10 clk =~ clk;
initial begin
reset_n = 0;
#201;
reset_n = 1;
#4000000; //仿真时是小数字,0.05ms闪烁一次
$stop;
end
endmodule
- 功能仿真结果
- 管脚分配
效果
1.2 移位方法2
之前我们直接使用了左移操作符实现移位操作,现在我们改进一下,使用位拼接操作来实现
我们该如何理解
led <= {led[6:0],led[7]}; //使用位拼接完成移位
//每次把led[7]的值放到到上一次的led[0]的位置,led[6]代替led[7]
画一张图帮助理解
2 利用之前的3-8译码器(学会模块调用模块)
- 先打开之前的 decoder_3_8的文件
- 把decoder_3_8.v 的文件复制到这个路径下(
E:\vivado_project\led_run\led_run.srcs\sources_1\new
)这是我的路径
- 然后就成了这样
- 添加到工程中来
- 然后,工程中就有了3-8译码器的文件
-
在led_run2的文件中例化3-8译码器的文件
- 首先我们需要生成一个新的计数器(代表a、b、c)
- 然后例化(类似仿真的例化)
- 由于之前在decoder_3_8中,out已经定义为了reg型,就不能再把led定义为reg型,所以led的reg需要去掉
- 下面我们仿真一下,看看是否成功实现了功能,我们不用再写一个仿真文件,只需要在之前的仿真文件下面改一下即可
- 分析仿真结果
从结果我们可以看出,与之前的一样,证明我们成功了
源文件文章来源:https://www.toymoban.com/news/detail-794855.html
module led_run2(
clk,
reset_n,
led
);
input clk;
input reset_n;
output [7:0] led;
reg [24:0] counter;
always@(posedge clk or negedge reset_n)
if(!reset_n)
counter <= 0;
else if(counter == 2500_0000-1)
// else if(counter == 2500-1) //为了仿真的时候方便观察,把数字改小
counter <= 0;
else
counter <= counter + 1'd1;
reg [2:0] counter2; //引入一个新的3位计数器
always@(posedge clk or negedge reset_n)
if(!reset_n)
counter2 <= 0;
// else if(counter2 == 7) 由于3位2进制数最大就是7,所以这个else if 可省略不写
// counter2 <= 0;
else if(counter == 2500_0000-1)
//else if(counter == 2500-1) //为了仿真的时候方便观察,把数字改小
counter2 <= counter2 + 1'b1;
decoder_3_8 decoder_3_8(
.a(counter2[2]),
.b(counter2[1]),
.c(counter2[0]),
.out(led)
);
endmodule
最后附上效果图
文章来源地址https://www.toymoban.com/news/detail-794855.html
到了这里,关于【FPGA】verilog基础语法与应用:位操作 / 模块调用——流水灯(跑马灯)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!