Verilog HDL 测量输入信号的正、负脉宽

源程序:

//测量输入信号的正、负脉宽
//输出数据为脉冲所占时钟周期数
`define WIDTH 16
module pulse_width_detect
(
	input i_clk,	//输入标准时钟
	input i_rstn,	//输入复位信号
	input i_en_o,	//输入使能输出
	input i_sig,	//输入待测信号
	input i_sel,	//输入选择输出
	output o_data_ok,	//输出数据有效
	output [`WIDTH-1:0]o_data	//输出数据
);

//r_sig 输入信号寄存器
//将输入信号与系统时钟同步化
reg r_sig;
always @(posedge i_clk)
	if(!i_rstn)
		r_sig<=0;
	else
		r_sig<=i_sig;

//r_rstn 复位信号寄存器
//用于检测复位信号的变化沿
reg r_rstn;
always @(posedge i_clk)
	r_rstn <= i_rstn;
	
//r_start、r_end 输入信号边沿寄存器
//有效时分别表示i_sig的上升沿、下降沿
reg r_start;
reg r_end;
always @(posedge i_clk)
	if(!i_rstn) begin
		r_start<=0;
		r_end <= 0;
	end else begin
		r_start<=(i_sig ==1 && r_sig == 0 && r_rstn == 1) ? 'b1 :'b0;//上升沿
		r_end  <=(i_sig ==0 && r_sig == 1 && r_rstn == 1) ? 'b1 :'b0;//下跳沿
	end

reg [`WIDTH-1:0]r_pos;
reg [`WIDTH-1:0]r_neg;
	
//r_start_pos、r_start_neg 高、低电平计时器开关
//有效时分别表示允许对高、低电平计时器计时
reg r_start_pos;
reg r_start_neg;
always @(posedge i_clk)
	if(!i_rstn) begin
		r_start_pos<=0;
		r_start_neg<=0;
	end else begin
		if(r_start) begin//在上升沿开始测量高电平周期
			if(r_pos ==0) r_start_pos <= 1;
			r_start_neg <= 0;
		end else if(r_end) begin//在下降沿开始测量低电平周期
			r_start_pos <= 0;
			if(r_neg ==0) r_start_neg <= 1;			
		end
		
	end

//每个时钟上升沿对有效输入信号计时
always @(posedge i_clk)
	if(!i_rstn)
		r_pos<=0;
	else
		if(r_start_pos)
			r_pos <= r_pos + 1;
			
//每个时钟上升沿对有效输入信号计时
always @(posedge i_clk)
	if(!i_rstn)
		r_neg<=0;
	else
		if(r_start_neg)
			r_neg <= r_neg + 1;

//测量时输出无效、不测量时输出有效
assign o_data_ok = ( r_start_pos |r_start_neg ) ? 'b0 : 'b1 ;

//当禁止输出时输出高阻;允许输出时,根据i_sel确定输出数据
assign o_data = i_en_o ? (i_sel ? r_pos : r_neg ): 'bz ;

endmodule
	


 

测试向量:

`define WIDTH 16
module freq_tb  ; 
 
  reg    i_sel   ; 
  wire    o_data_ok   ; 
  reg    i_en_o   ; 
  reg    i_clk   ; 
  wire  [`WIDTH-1:0]  o_data   ; 
  reg    i_sig   ; 
  reg    i_rstn   ; 
  pulse_width_detect
   DUT  ( 
       .i_sel (i_sel ) ,
      .o_data_ok (o_data_ok ) ,
      .i_en_o (i_en_o ) ,
      .i_clk (i_clk ) ,
      .o_data (o_data ) ,
      .i_sig (i_sig ) ,
      .i_rstn (i_rstn ) ); 
initial begin
    i_clk = 0;
    i_sig = 0;
    i_rstn = 0;
    i_sel = 0;
    #200
    i_rstn = 1;
end
initial begin
    i_en_o = 1;
    #2000
    i_en_o = 0;
    #1000
    i_en_o = 1;
end

always #50 i_clk = ~i_clk ;

reg [8:0]cnt;
always @(posedge i_clk)
   if(!i_rstn)
      cnt<=0;
   else 
      cnt<=cnt+ 1;

reg [12:0]cnt1;
always @(posedge i_clk)
   if(!i_rstn)
      cnt1<=0;
   else 
      cnt1<=cnt1+ 1;

always @(posedge i_clk)
   if(cnt1 == 12'hfff)
      begin
          i_rstn = 0;
          #200
          i_rstn = 1;
      end
      
always @(posedge i_clk)
   if(cnt == 128)
      i_sig <= {$random}%2;

always @(posedge i_clk)
   if(cnt == 10 )
      i_sel <= ~ i_sel ;
      
endmodule


 

功能仿真波形:

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanzhong104204

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值