当我们在进行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灯的状态来判断一些持续时间很短的瞬态信号的产生情况,而对于它们的发生时刻关系以及持续时间等详细信息的获取还是应该从示波器中得到。
文章评论(0条评论)
登录后参与讨论