赞
踩
研一从零开始学习verilog!!!此时不学何时学!
第一次写博客,以此激励自己努力学习!
我跟的视频教程是b站的一个up主,小梅哥爱漂流。
①编写端口代码:
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
①编写端口代码与例化
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,图像居然都一样,与视频不符合,这点很奇怪,难道是我开局没选和他一样的板子吗?这个问题后续再解决。
①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
④仿真结果
结果与前面一直, 依旧存在周期不对的问题。
今天学习了跑马灯的设计,结合了前面计数器和3-8译码器的知识。
新学的语法有:
①Led <= Led << 1意思为Led左移一位,<<为左移符号;
② Led<={Led[6:0],Led[7]},意思为向左循环移动一位。Led位宽为8,意思就是把第八位移到最后面,其他的依次前推一位,达到左循环移动一位的目的;
③工程文件的例化,需要先将要用的工程文件复制到现有工程的sources文件里面,然后会在Design Sources里面发现他,之后就直接在激励文件里面使用例化就可以。需要注意的是,如果有变量在被例化的文件里面已经定义类型了(如reg或wire),那在激励文件里面就不用再定义。
④在always块里面最好使用<=,不要直接使用=,防止图像发生错误
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。