本章节简介:
可以在任意时刻启动,可以重复启动,延时时长可调,单位可切换(ms/us),在50MHz时钟下的延时范围是1ms-85899ms/1us-85899us。
moduledelay //#(parameterN)//可以延时N*1ms/us (inputclk,rst_n, inputstart,//start上升沿有效 inputdelay_unit,//延时单位,high:ms/low:us outputfinish,finish_pose);//finish上升沿有效 regstart_reg0,start_reg1;//start两级缓存,用于边沿检测 regfinish_reg0,finish_reg1;//finish两级缓存 reg[31:0]cnt;//固定32位宽计数 reg[31:0]cnt_full; regrestart;//重新开始 wirestart_pose,full; always@(posedgeclkornegedgerst_n) begin if(!rst_n) begin cnt<= 32'd0; cnt_full <= 32'd10; //避免一开始finish置位 restart <= 1'b0; start_reg0 <= 1'b0; start_reg1 <= 1'b0; finish_reg0 <= 1'b0; finish_reg1 <= 1'b0; end else begin start_reg0 <= start; start_reg1 <= start_reg0; finish_reg1 <= finish_reg0; /**检测计时单位**/ if(delay_unit) cnt_full <= 32'd50_000*2-32'd2; //计时2ms 实际例化时用N代替: 32'd50_000*N-32'd2 else cnt_full <= 32'd50*2-32'd2; //计时2us /***************/ /**是否重新开始**/ if(start_pose) //检测到起始时刻 restart <= 1'b1; /****计时完成****/ else if(full) //延时结束 begin cnt <= 32'd0; //cnt归零 finish_reg0 <= 1'b1; //finish响应 restart <= 1'b0; end /***************/ /****计时开始****/ else if(restart) begin finish_reg0 <= 1'b0; //新一轮延时finish复位 cnt <= cnt+1'b1; end /***************/ /**等待新一轮计时**/ else begin cnt <= cnt; finish_reg0 <= finish_reg0; restart <= restart; end end end assign start_pose = (~start_reg1&start_reg0)?1'b1:1'b0; //start上升沿检测 assign finish_pose = (~finish_reg1&finish_reg0)?1'b1:1'b0; //finish上升沿检测 assign full = (cnt_full-cnt==0)?1'b1:1'b0; //检测是否计满 assign finish = finish_reg0; endmodule /**************************************************************************************************/ /***************************************modelsim********************************************/ `timescale 1ns/1ps module delay_tb(); reg clk,rst_n; reg start; wire finish,finish_pose; delay delay_u0 (.clk(clk), .rst_n(rst_n), .start(start), .delay_unit(1'b1), .finish(finish), .finish_pose(finish_pose)); //defparam delay_u0.N = 2; //延时2ms initial begin clk = 1'b0; rst_n = 1'b0; start = 1'b0; #1000 rst_n = 1'b1; #4010 start = 1'b1; #50 start = 1'b0; end always #10 clk = ~clk; endmodule
思路:
start端口给上升沿启动延时,延时结束端口finish置位(重新启动延时后复位)、finish的上升沿检测在模块内部已做好(端口finish_pose),直接调用即可,端口delay_unit置高选择ms,置低选择us,#(参数N )“是计时时长,例如计时8ms:”N = 8, .delay_unit(1'b1)“,实际例化时只需”defparam 例化名.N = 数值”。因为modelsim无法识别这种调用,所以直接用数值代替N进行测试。边沿检测会消耗两个时钟周期,所以cnt_full需要减2,并且将finish_reg0直接连到finish输出端口而不是用finish_reg1连接完成。
延时2ms测试的起始时刻(5010ns)和结束时刻(2005010ns):
-
FPGA
+关注
关注
1629文章
21729浏览量
602986 -
仿真
+关注
关注
50文章
4070浏览量
133552 -
Verilog
+关注
关注
28文章
1351浏览量
110074 -
代码
+关注
关注
30文章
4779浏览量
68521
原文标题:FPGA延时 Verilog HDL 实现
文章出处:【微信号:ZYNQ,微信公众号:ZYNQ】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论