原创 信号边缘捕获的应用浅谈

2011-5-8 20:36 2517 15 15 分类: FPGA/CPLD

当我们在进行FPGA调试的时候,有时可能会遇到身边的示波器带宽太小(几十MHz)或者更糟糕的示波器不在身边,而且现在的FPGA频率也是越来越高,低端示波器带宽却只有几十MHz,这时就很难捕捉到FPGA中只有几十ns或者持续时间更短的信号,这时候该如何调试?若仅仅只是想知道这些信号的发生情况,那么办法也还是有的,此时可以对它们进行边缘捕捉,然后再延长时间输出,这时,利用LED灯的状态我们就可以判断这些短暂信号的产生情况,便于调试。
下面就对这种方法做一下简要说明。
首先编写一个信号延时的模块加入到待测信号的后面,代码如下:
//=============================================================//
`timescale 1ns/1ns

 

module delayed_signal(clk,rst_n,din,dout);

 

//edge select: 1->positive edge is valid, 0->negative edge is valid
parameter edge_select = 1;
//set delayed time(us)
parameter [24:0] delay_time = 25'd5;
//output signa select: 1->valid output is high, 0->valid output is low
parameter level_out = 1;
//set cycle of main clock
parameter cycle_clk = 20;   //50MHz
parameter [29:0] count = delay_time * (1000/cycle_clk);
// 50MHz clock
//parameter [29:0] count = (delay_time<<5) + (delay_time<<4) + (delay_time<<1);

 

input  clk;
input  rst_n;
input  din;
output dout;

 

reg [29:0] clk_cnt;
reg        enable;
reg        din_r;
reg        dout_r;

 

wire dout;
wire pos_valid;
wire neg_valid;
wire edge_valid;
reg  pos_valid_r;
reg  neg_valid_r;

 

assign pos_valid = ~din_r & din;
assign neg_valid = din_r & ~din;
assign edge_valid = edge_select ? pos_valid_r : neg_valid_r;

 

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
       din_r <= 1'b0;
    else
       din_r <= din;
end

 

// record active edge
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
       begin
           pos_valid_r <= 1'b0;
           neg_valid_r <= 1'b0;
       end
    else if(pos_valid)
       pos_valid_r <= 1'b1;
    else if(neg_valid)
       neg_valid_r <= 1'b1;  
    else
       begin
           pos_valid_r <= 1'b0;
           neg_valid_r <= 1'b0;
       end
end

 

// start delay and output is active
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
       enable <= 1'b0;
    else if(edge_valid)
       enable <= 1'b1;
    else if(clk_cnt == count-1)
       enable <= 1'b0;
end

 

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
       begin
           clk_cnt <= 30'b0;
       end
    else if(enable)
       begin
           clk_cnt <= clk_cnt + 1'b1;
           if(clk_cnt >= count-1)
               clk_cnt <= 30'b0;
       end
end

 

// output level select
assign dout = level_out ? dout_r : ~dout_r;

 

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        dout_r <= 1'b0;
    else if(enable)
        dout_r <= 1'b1;
    else
        dout_r <= 1'b0;
end

 

endmodule
//==============================================================//
对于这个模块,要进行4个参数的配置:
(1)边缘选择(捕捉上升沿还是下降沿)
(2)延时时间选择(以us为单位,最大可达数十秒,通常几百ms到1s左右即可满足肉眼观测要求)
(3)输出有效电平选择(根据实际的高低电平需要进行配置)
(4)主时钟周期选择(便于内部延时计数器的配置)


为了便于说明,下面也给出一个简要的测试模块,代码如下:
//=============================================================//
`timescale 1ns/1ns
`include "./delayed_signal.v"

 

module delayed_signal_tb();

 

reg clk;
reg rst_n;
reg din;
wire dout;

 

parameter CYCLE = 20;

 

initial
begin
    clk = 0;
    forever
       #(CYCLE/2) clk = ~clk;
end

 

initial
begin
    reset_task(20);
    @(posedge clk);
    din = 0;
    @(posedge clk);
    din = 1;
   
    #(CYCLE*600) din = 0;
   
end


   
delayed_signal u_delayed_signal(.clk(clk),
                                .rst_n(rst_n),
                                .din(din),
                                .dout(dout));
defparam u_delayed_signal.cycle_clk = CYCLE;
defparam u_delayed_signal.edge_select = 1;   //posedge is active
defparam u_delayed_signal.delay_time = 500_000;   //delayed 500ms
defparam u_delayed_signal.level_out = 1;         //active output level is high

 

task reset_task;
input [15:0] reset_time;
begin
    rst_n = 0;
    #reset_time;
    rst_n = 1;
end


endtask

 

endmodule
//=============================================================//
通常,完成对上述4个参数的配置即可满足我们一般的测试需求。
不过,这种方法也是没办法的办法(解决一些燃眉之急,呵呵),它只能根据LED灯的状态来判断一些持续时间很短的瞬态信号的产生情况,而对于它们的发生时刻关系以及持续时间等详细信息的获取还是应该从示波器中得到。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
15
关闭 站长推荐上一条 /3 下一条