本章节简介:
可以在任意时刻启动,可以重复启动,延时时长可调,单位可切换(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):
全部0条评论
快来发表一下你的评论吧 !