企业资质查询官方网站,微服务网站开发,wordpress文章自动加p,河北省建设工程安全生产监督管理网站文章目录 该系列目录#xff1a;设计目标设计思路RTL 及 Testbench仿真结果存在的问题#xff1f;改善后的代码RTL代码testbench代码 仿真结果 案例和代码来自小梅哥课程#xff0c;本人仅对知识点做做笔记#xff0c;如有学习需要请支持官方正版。 该系列目录#xff1a;… 文章目录 该系列目录设计目标设计思路RTL 及 Testbench仿真结果存在的问题改善后的代码RTL代码testbench代码 仿真结果 案例和代码来自小梅哥课程本人仅对知识点做做笔记如有学习需要请支持官方正版。 该系列目录
Verilog线性序列机点灯案例(一)
设计目标
我们的FPGA的时钟频率为50MHz即每个周期20ns。 因此在该时钟下时间和周期数的对应关系为
持续时间对应周期数0.25s12,500,000 cycles0.5s25,000,000 cycles0.75s37,500,000 cycles1s50,000,000 cycles
我们的目标是让LED以**【亮0.25秒-灭0.5秒-亮0.75秒-灭1秒】**的规律持续循环闪烁。
设计思路 为了完成这样的规律性闪烁需要一个计数器计数满2.5秒归零即当上升沿采样到125,000,000-1时计数器归零。 然后led灯根据当前计数器的数值设置led的亮灭图中已经标注了led跳变时的counter数值。下面直接上代码
RTL 及 Testbench
led_ctrl1.v 是RTL代码
module led_ctrl1(clk,rst_n,led_out
);input clk;input rst_n;output reg led_out;reg [26:0] counter;//第一个always负责counter计数器的逻辑always(posedge clk or negedge rst_n) beginif(!rst_n) begincounter 0;end else if(counter 125_000_000-1) begincounter 0;end else begincounter counter 1;endend//第二个always负责led_out闪烁的逻辑//亮0.25s-灭0.5秒-亮0.75秒-灭1秒always(posedge clk or negedge rst_n) beginif(!rst_n) beginled_out 0;end else if(counter 0) beginled_out 1;end else if(counter 12_500_000) beginled_out 0;end else if(counter 37_500_000) beginled_out 1;end else if(counter 75_000_000) beginled_out 0;end endendmoduletb_led_ctrl1.v是testbench代码
timescale 1ns / 1nsmodule tb_led_ctrl1();reg clk;reg rst_n;wire led_out;initial clk 1;always #10 clk ~clk;led_ctrl1 led_ctrl1_inst0(.clk(clk),.rst_n(rst_n),.led_out(led_out));initial beginrst_n 0;#201;rst_n 1;#250_000_000$stop;end
endmodule仿真结果
从图中黄色marker标注下的时间间隔可以看出仿真结果和预期目标一致。
存在的问题
如果到此就结束了那么案例二和一并没有多大区别。 实际上按照刚才的实现方式可以完成功能但存在如下问题
仿真时间过长 为了在实际上板时观察到led闪烁的效果我们的闪烁都是秒级的vivado仿真一秒时间几乎需要十几秒才能完成能否减少仿真时间不影响功能可读性较差 在我们的代码中0.25s,0.75s这些时间尺度都是用具体的计数器的周期数来表示的数字太大不好理解如何解决
针对以上问题观察我们的需求是让LED以**【亮0.25秒-灭0.5秒-亮0.75秒-灭1秒】**循环那么最基本的单位可以视为0.25秒我们可以使用两个计数器第一个计数器计数到0.25秒12500_000 - 1个cycles时第二个计数器加1。按照这个思路我们在设置led时只需要关注好第二个计数器即可1亮2、3灭4、5、6亮7、8、9、10灭显然可读性是比0亮12_500_000灭好多了。 此外针对仿真时间过长的问题我们可以在RTL模块中定义一个parameter时间单元而在testbench仿真中重新缩小该时间单元1000倍实际上板时只会烧录RTL模块这样既节省了仿真时间又不影响功能。
改善后的代码
RTL代码
module led_ctrl1(clk,rst_n,led_out
);input clk;input rst_n;output reg led_out;parameter MCNT 12500_000 - 1;reg [26:0] counter0;always(posedge clk or negedge rst_n) beginif(!rst_n)counter0 0 ;else if(counter0 MCNT)counter0 0;elsecounter0 counter0 1d1;endreg [3:0] counter1;always(posedge clk or negedge rst_n) beginif(!rst_n)counter1 0 ;else if(counter0 MCNT) beginif(counter1 9)counter1 0;elsecounter1 counter1 1d1;endelsecounter1 counter1;endalways(posedge clk or negedge rst_n)if(!rst_n)led_out 0;else begincase(counter1)0:led_out 1d1;1:led_out 1d0;2:led_out 1d0;3:led_out 1d1;4:led_out 1d1;5:led_out 1d1;6:led_out 1d0;7:led_out 1d0;8:led_out 1d0;9:led_out 1d0;default:led_out led_out;endcaseendendmoduletestbench代码
timescale 1ns / 1nsmodule tb_led_ctrl1();reg clk;reg rst_n;wire led_out;initial clk 1;always #10 clk ~clk;led_ctrl1 led_ctrl1_inst0(.clk(clk),.rst_n(rst_n),.led_out(led_out));defparam led_ctrl1.MCNT 12500 - 1; initial beginrst_n 0;#201;rst_n 1;#20_000_000;$stop;end
endmodule
仿真结果