当前位置:首页 > > ZYNQ


本章节 简介:

可以在任意时刻启动,可以重复启动,延时时长可调,单位可切换(ms/us),在50MHz时钟下的延时范围是1ms-85899ms/1us-85899us。

源代码和modelsim仿真代码:

 module delay



 //#(parameter N )  //可以延时N*1ms/us (input clk,rst_n,

 input start,     //start上升沿有效

 input delay_unit, //延时单位,high:ms/low:us

 output finish,finish_pose); //finish上升沿有效

 reg start_reg0,start_reg1;  //start两级缓存,用于边沿检测

 reg finish_reg0,finish_reg1;  //finish两级缓存

 reg [31:0]cnt;  //固定32位宽计数

 reg [31:0]cnt_full;

 reg restart; //重新开始

 wire start_pose,full;

 always @(posedge clk or negedge rst_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):



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭