FPGA占空比测量 帮忙误差解决
时间:10-02
整理:3721RD
点击:
代码 如下 在高电平计数到86ms以上时就会出现很大的误差 仿真也没问题 是什么原因呢?
module dutycycle(
clk ,
rst_n ,
clk_400M ,
signal ,
en_d ,
flag_d ,
dout
);
//输入信号定义
input clk ;
input rst_n ;
input clk_400M ;
input signal ;
input en_d ;
//输出信号定义
output[31:0] dout ;
output flag_d ;
//输出信号reg定义
reg [31:0] dout ;
reg flag_d ;
reg [31:0] time_h ;
reg [31:0] time_a ;
//中间信号定义
reg signal_ff0;
reg signal_ff1;
reg signal_ff2;
reg [31:0] time_h_buf;
reg [31:0] time_a_buf;
reg [2:0] state ;
wire jump_p1 ;
wire jump_p2 ;
wire jump_n ;
assign jump_p1 = signal_ff0 && ~signal_ff1; //第一个上升沿
assign jump_p2 = signal_ff1 && ~signal_ff2; //第二个上升沿
assign jump_n = ~signal_ff0 && signal_ff1; //第一个下降沿
always@(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
signal_ff0 <= 0;
signal_ff1 <= 0;
signal_ff2 <= 0;
end
else begin
signal_ff0 <= signal;
signal_ff1 <= signal_ff0;
signal_ff2 <= signal_ff1;
end
end
//占空比测量
always @(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
state <= 0;
end
else if(jump_p1&&state==0&&en_d)begin
state <= 1;
end
else if(jump_n&&state==1)begin
state <= 2;
end
else if(jump_p2&&state==2)begin
state <= 3;
end
else if(state==3)begin
state <= 4;
end
else if (state==4)begin
state <= 0;
end
end
always @(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 32'd0;
flag_d <= 0;
time_h <= 32'd0;
time_a <= 32'd0;
time_h_buf <= 32'd0;
time_a_buf <= 32'd0;
end
else begin
case(state)
3'd1:begin
time_h_buf <= time_h_buf + 1'b1;
time_a_buf <= time_a_buf + 1'b1;
end
3'd2:begin
time_h_buf <= time_h_buf;
time_a_buf <= time_a_buf + 1'b1;
end
3'd3:begin
time_h <= time_h_buf;
time_a <= time_a_buf;
end
3'd4:begin
dout <= 1+1000* time_h/time_a;
flag_d <= 1'd1;
end
default:begin
dout <= 32'd0;
flag_d <= 0;
//time_h <= 32'd0;
//time_a <= 32'd0;
time_h_buf <= 32'd0;
time_a_buf <= 32'd0;
end
endcase
end
end
endmodule
module dutycycle(
clk ,
rst_n ,
clk_400M ,
signal ,
en_d ,
flag_d ,
dout
);
//输入信号定义
input clk ;
input rst_n ;
input clk_400M ;
input signal ;
input en_d ;
//输出信号定义
output[31:0] dout ;
output flag_d ;
//输出信号reg定义
reg [31:0] dout ;
reg flag_d ;
reg [31:0] time_h ;
reg [31:0] time_a ;
//中间信号定义
reg signal_ff0;
reg signal_ff1;
reg signal_ff2;
reg [31:0] time_h_buf;
reg [31:0] time_a_buf;
reg [2:0] state ;
wire jump_p1 ;
wire jump_p2 ;
wire jump_n ;
assign jump_p1 = signal_ff0 && ~signal_ff1; //第一个上升沿
assign jump_p2 = signal_ff1 && ~signal_ff2; //第二个上升沿
assign jump_n = ~signal_ff0 && signal_ff1; //第一个下降沿
always@(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
signal_ff0 <= 0;
signal_ff1 <= 0;
signal_ff2 <= 0;
end
else begin
signal_ff0 <= signal;
signal_ff1 <= signal_ff0;
signal_ff2 <= signal_ff1;
end
end
//占空比测量
always @(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
state <= 0;
end
else if(jump_p1&&state==0&&en_d)begin
state <= 1;
end
else if(jump_n&&state==1)begin
state <= 2;
end
else if(jump_p2&&state==2)begin
state <= 3;
end
else if(state==3)begin
state <= 4;
end
else if (state==4)begin
state <= 0;
end
end
always @(posedge clk_400M or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 32'd0;
flag_d <= 0;
time_h <= 32'd0;
time_a <= 32'd0;
time_h_buf <= 32'd0;
time_a_buf <= 32'd0;
end
else begin
case(state)
3'd1:begin
time_h_buf <= time_h_buf + 1'b1;
time_a_buf <= time_a_buf + 1'b1;
end
3'd2:begin
time_h_buf <= time_h_buf;
time_a_buf <= time_a_buf + 1'b1;
end
3'd3:begin
time_h <= time_h_buf;
time_a <= time_a_buf;
end
3'd4:begin
dout <= 1+1000* time_h/time_a;
flag_d <= 1'd1;
end
default:begin
dout <= 32'd0;
flag_d <= 0;
//time_h <= 32'd0;
//time_a <= 32'd0;
time_h_buf <= 32'd0;
time_a_buf <= 32'd0;
end
endcase
end
end
endmodule
dout <= 1+1000* time_h/time_a;
好像这里有问题,400M时钟在86mS里计数0x20ce700,乘1000之后=0x8 0266 5800,超过了32位吧?是不是溢出了?
另外,好像极限测量时间不是86mS,好像超过10.7mS乘法就溢出了,但是编译时可能结合了除法的优化,使得实际的测量乘法的上限到达了0x7 ffff ffff。请改一里再试验一下,祝好运!
先把乘1000改成乘100试验一下,如果上限变了,基本就确定是溢出了。
看了回复,觉得就是这里的错误 谢谢啦
现在的问题是我把1000放在最后面乘的话数据是0 这该怎么改呢?
"1000放在最后面乘的话数据是0"是因为先算了除法,这个除法是整数除法,没小数部分,所以结果得0.
可能有两个办法可以解决:
1、因为乘1000改小一些可以提高上限,所以可以用分段的方法,对不同测量区间乘以不同的系数。
2、为了不损失精度,需要提高time_a 和time_h 的位数,不知您的编译器是否直接支持64位乘除?如果不支持,就得分解成为多次32位乘除法。会比较麻烦。 如果换成浮点运算,只是理论上可行,但是我没用逻辑做过。FPGA中用CPU软核来计算这个64位乘除法,或浮点乘除法是可行的。
谢谢你为我解决了这个问题