前言
研一从零开始学习verilog!!!此时不学何时学!
第一次写博客,以此激励自己努力学习!
我跟的视频教程是b站的一个up主,小梅哥爱漂流。
一、vivado是什么?
二、跑马灯设计(让8个LED灯以每个0.5s的速率循环闪烁)
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==25000-1)//本来应该是25000000-1的,但是为了更快出图像,此处可调整一下数量级
counter<=0;
else
counter<=counter+1'd1;
其中,一定是<=,如果直接用=,则波形图会出现错误,从00000010到00000100的时间会非常短,导致整个图像看起来就是每次左移两位。
③LED灯循环闪烁
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led<=0000_0001;
/* else if(counter==25000-1)begin
if(Led==8'b1000_0000)
Led<=8'b0000_0001;
else
Led <= Led << 1;//Led左移一位
end
*/
else if(counter==25000-1)
Led<={Led[6:0],Led[7]};//向左循环移动一位
else
Led<=Led;
两个/之间的内容为注释掉的内容。要实现8个LED循环闪烁,可用<=进行左移,但这样LED不会循环,如果不加限制条件,会一直出现0000——0000的情况;而直接使用位拼接 Led<={Led[6:0],Led[7]},即循环左移一位。最后加一个endmodule即可。
④代码整合
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==25000-1)
counter<=0;
else
counter<=counter+1'd1;//一定是<=,如果直接用=,则波形图会出现错误,从00000010到00000100的时间会非常短,导致整个图像看起来就是每次左移两位
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led<=0000_0001;
/* else if(counter==25000-1)begin
if(Led==8'b1000_0000)
Led<=8'b0000_0001;
else
Led <= Led << 1;//Led左移一位
end
*/
else if(counter==25000-1)
Led<={Led[6:0],Led[7]};//向左循环移动一位
else
Led<=Led;
endmodule
2.激励文件
①编写端口代码与例化
module Led_run_tb();
reg Clk;
reg Reset_n;
wire [7:0]Led;
Led_run Led_run(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
②编写时钟信号与复位信号
initial Clk=1;
always #10 Clk = !Clk;//10ns翻转一次
initial begin
Reset_n=0;
#201;//错开时钟上升沿
Reset_n=1;
#400000000;//4s之后灯全部跑完
$stop;
end
③代码整合
`timescale 1ns/1ns;
module Led_run_tb();
reg Clk;
reg Reset_n;
wire [7:0]Led;
Led_run Led_run(
//Led_run Led_run_38decoder( //调用3-8译码器的方法
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk=1;
always #10 Clk = !Clk;
initial begin
Reset_n=0;
#201;
Reset_n=1;
#4000000000;//4s之后灯全部跑完
$stop;
end
endmodule
④仿真结果
波形变化没问题,但是波形变化的周期出了大问题,LED灯循环居然只花了160ns,这与设计的差太多,无论我计数器那里改成25000000-1还是25000-1,图像居然都一样,与视频不符合,这点很奇怪,难道是我开局没选和他一样的板子吗?这个问题后续再解决。
3.调用3-8译码器实现走马灯
①copy文件到指定目录
先将3-8译码器的工程文件copy到走马灯的sources文件里面,然后会在Design Sources里面发现他
②例化
reg [2:0]counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2<=0;
/* else if (counter2==7)
counter2<=0; */ //这两行也可以不写,因为counter2位宽为3,最大值为7,当达到7时会自动变为0然后继续计数
else
counter2<=counter2+1;
//调用3-8译码器的模块
decoder3_8 decoder3_8(
.a( counter2[2]),
.b( counter2[1]),
.c( counter2[0]),
.out(Led)
);
由于例化了3-8译码器,所以此时Led只作为接口,out已经在3-8译码器中定义了reg类型,Led就不用定义了
③代码整合
3-8译码器代码
module decoder3_8(
a,b,c,out
);
input a;
input b;
input c;
output reg [7:0]out;//位宽是8位,类型为reg类型,与always相配
//以always块描述的信号赋值,被赋值对象必须定义为reg类型
//b代表二进制;3'b101 8'b0000_1010
//d代表十进制;3'd5 8'd10
//h代表十六进制; 8'ha
always@(*)//*代表a b c
case({a,b,c})//{a,b,c}变成了一个三位的信号,这种操作叫做位拼接
3'b000:out=8'b0000_0001;
3'b001:out=8'b0000_0010;
3'b010:out=8'b0000_0100;
3'b011:out=8'b0000_1000;
3'b100:out=8'b0001_0000;
3'b101:out=8'b0010_0000;
3'b110:out=8'b0100_0000;
3'b111:out=8'b1000_0000;
endcase
endmodule
设计代码
`timescale 1ns/1ns;
module Led_run_tb();
reg Clk;
reg Reset_n;
wire [7:0]Led;
//Led_run Led_run(
Led_run Led_run_38decoder( //调用3-8译码器的方法
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk=1;
always #10 Clk = !Clk;
initial begin
Reset_n=0;
#201;
Reset_n=1;
#4000000000;//4s之后灯全部跑完
$stop;
end
endmodule
激励文件代码
module Led_run(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output [7:0]Led;//因为例化了3-8译码器,所以此时Led只作为接口,out已经在3-8译码器中定义了reg类型,Led就不用定义了
reg [25:0]counter;
reg [2:0]counter2;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter<=0;
else if(counter==25000000-1)
counter<=0;
else
counter<=counter+1;//一定是<=,如果直接用=,则波形图会出现错误,从00000010到00000100的时间会非常短,导致整个图像看起来就是每次左移两位
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter2<=0;
/* else if (counter2==7)
counter2<=0; */ //这两行也可以不写,因为counter2位宽为3,最大值为7,当达到7时会自动变为0然后继续计数
else
counter2<=counter2+1;
//调用3-8译码器的模块
decoder3_8 decoder3_8(
.a( counter2[2]),
.b( counter2[1]),
.c( counter2[0]),
.out(Led)
);
endmodule
④仿真结果
结果与前面一直, 依旧存在周期不对的问题。文章来源:https://www.toymoban.com/news/detail-785349.html
总结
今天学习了跑马灯的设计,结合了前面计数器和3-8译码器的知识。
新学的语法有:
①Led <= Led << 1意思为Led左移一位,<<为左移符号;
② Led<={Led[6:0],Led[7]},意思为向左循环移动一位。Led位宽为8,意思就是把第八位移到最后面,其他的依次前推一位,达到左循环移动一位的目的;
③工程文件的例化,需要先将要用的工程文件复制到现有工程的sources文件里面,然后会在Design Sources里面发现他,之后就直接在激励文件里面使用例化就可以。需要注意的是,如果有变量在被例化的文件里面已经定义类型了(如reg或wire),那在激励文件里面就不用再定义。
④在always块里面最好使用<=,不要直接使用=,防止图像发生错误文章来源地址https://www.toymoban.com/news/detail-785349.html
到了这里,关于从零开始学习vivado——day4 跑马灯(让8个LED灯以每个0.5s的速率循环闪烁)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!