verilog奇怪的频率统计代码

MengXP 2016-06-23 07:15:54
想要实现一个频率统计

首先生成一个1hz的信号用于重置计数器
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt_1hz <= 32'd0;
clk_1hz <= 1'd0;
end
else if(cnt_1hz == 32'd99999999)
begin
cnt_1hz <= 32'd0;
clk_1hz <= ~clk_1hz;
end
else
cnt_1hz <= cnt_1hz + 32'd1;
end


pclk是一个大概85MHz左右的稳定信号,我想统计这个信号的实际频率。
我写了如下代码,但是实际运行发现pclk_freq的值非常大,已经达到了G级,结果明显是错的

always @(posedge pclk or posedge clk_1hz or negedge rst_n)
begin
if(!rst_n)
begin
pclk_cnt <= 32'd0;
pclk_freq <= 32'd0;
pclk_rst <= 32'd0;
end
else if(pclk)
if(pclk_rst)
begin
pclk_cnt <= 32'd1;
pclk_rst <= 1'd0;
end
else
pclk_cnt <= pclk_cnt + 1'b1;
else if(clk_1hz)
begin
pclk_freq <= pclk_cnt;
pclk_rst <= 1'd1;
end
end

我调整了代码的elseif分支判断顺序
always @(posedge pclk or posedge clk_1hz or negedge rst_n)
begin
if(!rst_n)
begin
pclk_cnt <= 32'd0;
pclk_freq <= 32'd0;
pclk_rst <= 32'd0;
end
else if(clk_1hz)
begin
pclk_freq <= pclk_cnt;
pclk_rst <= 1'd1;
end
else if(pclk)
if(pclk_rst)
begin
pclk_cnt <= 32'd1;
pclk_rst <= 1'd0;
end
else
pclk_cnt <= pclk_cnt + 1'b1;
end

也就是说我把判断clk_1hz上升沿的elseif判断提前了,这时pclk_freq的结果是准确的,可是仍然有一个小问题
我是用nios2程序去读这个pclk_freq的,读几十次总有那么一次是错的,结果远小于85M大概只有16M左右的样子。

我想知道的是我上面两种不同的elseif写法为什么会导致频率统计错误呢?是因为elseif分支太长导致信号传递比被统计的信号慢?这种情况是叫时序不满足吗?
另外我最后改进的这个代码为什么偶尔也会统计错误呢?
统计频率还有没有更好的写法呢?求高手赐教!
...全文
651 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
DDRn++ 2016-06-26
  • 打赏
  • 举报
回复
频率计的关键点是,在门限内检测被测试频率的上升沿。
fly 100% 2016-06-24
  • 打赏
  • 举报
回复
第一种肯定是错误的, else if(pclk) if(pclk_rst) begin pclk_cnt <= 32'd1; pclk_rst <= 1'd0; end else pclk_cnt <= pclk_cnt + 1'b1; else if(clk_1hz) begin pclk_freq <= pclk_cnt; pclk_rst <= 1'd1; end 在clk_1hz为高定平是,计算一直在复位,为低电平是 pclk_freq <= pclk_cnt;这条却不能被执行。只有在不稳定状态才会赋值,计算结果不能保证。 第二种方法效果略微好点就是,在在clk_1hz为低电平市,pclk的累加一直在进行,当clk_1hz为高电平是 pclk_freq <= pclk_cnt;这条却能被执行。然后计算复位。 fpga中像verilog和vhdl都是硬件语言,不能简单的当成c语言这样去用,fpga是并行执行计算的,你这个条理不清晰,切分成小模块,去写。 这里给你一个思路:两个模块,1.pclk posedge 作为敏感信号,输入信号 input  start 来启动累加,输出信号 output pclk_cnt 累加结果, 2模块 clk_1hz posedge 作为敏感信号,两个信号,输入是1模块的pclk_cnt 累加结果,输出信号就是clk_1hz posedge 这个信号产生start  给1模块去启动累加,这样就可以得到,clk_1hz 以周期pclk的边沿数量了,这里可以做一个优化就是 2模块每几个周期产生一个start  这样就可以减小一下误差,
MengXP 2016-06-24
  • 打赏
  • 举报
回复
引用 1 楼 xuweiwei1860 的回复:
在clk_1hz为高定平是,计算一直在复位,
我的always块指明了是clk_1hz的上升沿啊,应该只有上升沿到来的一瞬间才执行,不会在高电平期间执行啊,这是时序电路不是组合电路啊。

6,125

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 硬件设计
社区管理员
  • 硬件设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧