源程序:
//测量两路信号相位差
//要求两路信号除相位不同外,其他信息必须完全一致
`define WIDTH 16
module phase_diff_detect
(
input i_clk, //输入标准时钟
input i_rstn, //输入复位信号
input i_en_o, //输入使能输出
input i_sig1, //输入待测信号1
input i_sig2, //输入待测信号2
output o_data_ok, //输出数据有效
output [`WIDTH - 1:0]o_data //输出数据
);
//r_sig1 输入信号1寄存器
//将输入信号1与系统时钟同步化
reg r_sig1;
always @(posedge i_clk)
if(!i_rstn)
r_sig1<=0;
else
r_sig1<=i_sig1;
//r_sig2 输入信号2寄存器
//将输入信号2与系统时钟同步化
reg r_sig2;
always @(posedge i_clk)
if(!i_rstn)
r_sig2<=0;
else
r_sig2<=i_sig2;
//r_rstn 复位信号寄存器
//用于检测复位信号的变化沿
reg r_rstn;
always @(posedge i_clk)
r_rstn <= i_rstn;
//r_start1输入信号1上升沿寄存器
reg r_start1;
always @(posedge i_clk)
if(!i_rstn)
r_start1<=0;
else
r_start1<=(i_sig1 ==1 && r_sig1 == 0 && r_rstn == 1) ? 'b1 :'b0;//上升沿
//r_start2输入信号2上升沿寄存器
reg r_start2;
always @(posedge i_clk)
if(!i_rstn)
r_start2<=0;
else
r_start2<=(i_sig2 ==1 && r_sig2 == 0 && r_rstn == 1) ? 'b1 :'b0;//上升沿
//r_data数据寄存器
reg [`WIDTH - 1:0] r_data;
//r_detect_avail 测量相位差计时允许开关
//当处于两个信号上升沿之间时开关打开,其他情况下开关关闭
reg r_detect_avail;
always @(posedge i_clk)
if(!i_rstn)
r_detect_avail<=0 ;
else
if(r_start1 && r_data == 0)
r_detect_avail <= 1 ;
else if(r_start2)
r_detect_avail <= 0 ;
else
r_detect_avail <= r_detect_avail ;
//相位差计时
always @(posedge i_clk)
if(!i_rstn)
r_data<=0 ;
else
if(r_detect_avail)
r_data <= r_data + 1;
//测量时输出无效、不测量时输出有效
assign o_data_ok = r_detect_avail ? 'b0 : 'b1;
assign o_data = i_en_o ? r_data : 'bz;
endmodule
测试向量:
`define WIDTH 16
module phase_tb ;
reg i_sig1 ;
wire o_data_ok ;
reg i_sig2 ;
reg i_en_o ;
reg i_clk ;
wire [`WIDTH - 1:0] o_data ;
reg i_rstn ;
phase_diff_detect
DUT (
.i_sig1 (i_sig1 ) ,
.o_data_ok (o_data_ok ) ,
.i_sig2 (i_sig2 ) ,
.i_en_o (i_en_o ) ,
.i_clk (i_clk ) ,
.o_data (o_data ) ,
.i_rstn (i_rstn ) );
initial begin
i_clk = 0;
i_sig1 = 0;
i_rstn = 0;
#200
i_rstn = 1;
end
initial begin
i_en_o = 1;
#20000
i_en_o = 0;
#30000
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;
always @(posedge i_clk)
if(!i_rstn)
i_sig1<= 0;
else
if(cnt == 10)
i_sig1 <= {$random}%2;
always @(posedge i_clk)
if(!i_rstn)
i_sig2<= 0;
else
i_sig2 <= #8000 i_sig1;
endmodule
功能仿真波形:
![](https://img-my.csdn.net/uploads/201206/21/1340265805_5967.jpg)